zstd: Update to upstream version 1.5.0
Release notes: https://github.com/facebook/zstd/releases/tag/v1.5.0
This commit is contained in:
parent
42f8bfaff0
commit
5bea1370f0
|
@ -447,7 +447,7 @@ License: Zlib
|
||||||
|
|
||||||
Files: ./thirdparty/zstd/
|
Files: ./thirdparty/zstd/
|
||||||
Comment: Zstandard
|
Comment: Zstandard
|
||||||
Copyright: 2016-2020, Facebook, Inc.
|
Copyright: 2016-2021, Facebook, Inc.
|
||||||
License: BSD-3-clause
|
License: BSD-3-clause
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -706,11 +706,11 @@ Files extracted from upstream source:
|
||||||
## zstd
|
## zstd
|
||||||
|
|
||||||
- Upstream: https://github.com/facebook/zstd
|
- Upstream: https://github.com/facebook/zstd
|
||||||
- Version: 1.4.8 (97a3da1df009d4dc67251de0c4b1c9d7fe286fc1, 2020)
|
- Version: 1.5.0 (a488ba114ec17ea1054b9057c26a046fc122b3b6, 2021)
|
||||||
- License: BSD-3-Clause
|
- License: BSD-3-Clause
|
||||||
|
|
||||||
Files extracted from upstream source:
|
Files extracted from upstream source:
|
||||||
|
|
||||||
- lib/{common/,compress/,decompress/,zstd.h}
|
- `lib/{common/,compress/,decompress/,zstd.h,zstd_errors.h}`
|
||||||
- LICENSE
|
- `LICENSE`
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* bitstream
|
* bitstream
|
||||||
* Part of FSE library
|
* Part of FSE library
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -90,6 +90,7 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* target attribute */
|
/* target attribute */
|
||||||
#ifndef __has_attribute
|
#ifndef __has_attribute
|
||||||
#define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
#define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Facebook, Inc.
|
* Copyright (c) Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* debug
|
* debug
|
||||||
* Part of FSE library
|
* Part of FSE library
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* debug
|
* debug
|
||||||
* Part of FSE library
|
* Part of FSE library
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* Common functions of New Generation Entropy library
|
* Common functions of New Generation Entropy library
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -21,8 +21,8 @@ extern "C" {
|
||||||
/* ****************************************
|
/* ****************************************
|
||||||
* Dependencies
|
* Dependencies
|
||||||
******************************************/
|
******************************************/
|
||||||
#include "zstd_deps.h" /* size_t */
|
#include "../zstd_errors.h" /* enum list */
|
||||||
#include "zstd_errors.h" /* enum list */
|
#include "zstd_deps.h" /* size_t */
|
||||||
|
|
||||||
|
|
||||||
/* ****************************************
|
/* ****************************************
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* FSE : Finite State Entropy codec
|
* FSE : Finite State Entropy codec
|
||||||
* Public Prototypes declaration
|
* Public Prototypes declaration
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
@ -352,7 +352,7 @@ size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
|
||||||
size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
|
size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
|
||||||
/**< build a fake FSE_DTable, designed to always generate the same symbolValue */
|
/**< build a fake FSE_DTable, designed to always generate the same symbolValue */
|
||||||
|
|
||||||
#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue))
|
#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)
|
||||||
#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
|
#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
|
||||||
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize);
|
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize);
|
||||||
/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */
|
/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* FSE : Finite State Entropy decoder
|
* FSE : Finite State Entropy decoder
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
@ -310,6 +310,12 @@ size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size
|
||||||
return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0);
|
return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
short ncount[FSE_MAX_SYMBOL_VALUE + 1];
|
||||||
|
FSE_DTable dtable[1]; /* Dynamically sized */
|
||||||
|
} FSE_DecompressWksp;
|
||||||
|
|
||||||
|
|
||||||
FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
|
FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
|
||||||
void* dst, size_t dstCapacity,
|
void* dst, size_t dstCapacity,
|
||||||
const void* cSrc, size_t cSrcSize,
|
const void* cSrc, size_t cSrcSize,
|
||||||
|
@ -318,33 +324,37 @@ FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
|
||||||
{
|
{
|
||||||
const BYTE* const istart = (const BYTE*)cSrc;
|
const BYTE* const istart = (const BYTE*)cSrc;
|
||||||
const BYTE* ip = istart;
|
const BYTE* ip = istart;
|
||||||
short counting[FSE_MAX_SYMBOL_VALUE+1];
|
|
||||||
unsigned tableLog;
|
unsigned tableLog;
|
||||||
unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
|
unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
|
||||||
FSE_DTable* const dtable = (FSE_DTable*)workSpace;
|
FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;
|
||||||
|
|
||||||
|
DEBUG_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);
|
||||||
|
if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);
|
||||||
|
|
||||||
/* normal FSE decoding mode */
|
/* normal FSE decoding mode */
|
||||||
size_t const NCountLength = FSE_readNCount_bmi2(counting, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
|
{
|
||||||
if (FSE_isError(NCountLength)) return NCountLength;
|
size_t const NCountLength = FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
|
||||||
if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
|
if (FSE_isError(NCountLength)) return NCountLength;
|
||||||
assert(NCountLength <= cSrcSize);
|
if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
|
||||||
ip += NCountLength;
|
assert(NCountLength <= cSrcSize);
|
||||||
cSrcSize -= NCountLength;
|
ip += NCountLength;
|
||||||
|
cSrcSize -= NCountLength;
|
||||||
|
}
|
||||||
|
|
||||||
if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);
|
if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);
|
||||||
workSpace = dtable + FSE_DTABLE_SIZE_U32(tableLog);
|
workSpace = wksp->dtable + FSE_DTABLE_SIZE_U32(tableLog);
|
||||||
wkspSize -= FSE_DTABLE_SIZE(tableLog);
|
wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
|
||||||
|
|
||||||
CHECK_F( FSE_buildDTable_internal(dtable, counting, maxSymbolValue, tableLog, workSpace, wkspSize) );
|
CHECK_F( FSE_buildDTable_internal(wksp->dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );
|
||||||
|
|
||||||
{
|
{
|
||||||
const void* ptr = dtable;
|
const void* ptr = wksp->dtable;
|
||||||
const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
|
const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
|
||||||
const U32 fastMode = DTableH->fastMode;
|
const U32 fastMode = DTableH->fastMode;
|
||||||
|
|
||||||
/* select fast mode (static) */
|
/* select fast mode (static) */
|
||||||
if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 1);
|
if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 1);
|
||||||
return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 0);
|
return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* huff0 huffman codec,
|
* huff0 huffman codec,
|
||||||
* part of Finite State Entropy library
|
* part of Finite State Entropy library
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
@ -192,6 +192,7 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||||
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
|
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
|
||||||
size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
|
size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
|
||||||
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
|
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
|
||||||
|
size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);
|
||||||
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
|
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
|
||||||
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
|
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
|
||||||
int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
|
int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
|
||||||
|
@ -278,7 +279,7 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
|
||||||
* a required workspace size greater than that specified in the following
|
* a required workspace size greater than that specified in the following
|
||||||
* macro.
|
* macro.
|
||||||
*/
|
*/
|
||||||
#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10)
|
#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))
|
||||||
#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
|
#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
|
||||||
|
|
||||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -143,9 +143,7 @@ MEM_STATIC size_t MEM_swapST(size_t in);
|
||||||
* Prefer these methods in priority order (0 > 1 > 2)
|
* Prefer these methods in priority order (0 > 1 > 2)
|
||||||
*/
|
*/
|
||||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
#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__) )
|
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||||
# define MEM_FORCE_MEMORY_ACCESS 2
|
|
||||||
# elif defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
|
||||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -308,7 +306,7 @@ MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)
|
||||||
|
|
||||||
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
MEM_STATIC U32 MEM_readLE24(const void* memPtr)
|
||||||
{
|
{
|
||||||
return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);
|
return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
|
MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* xxHash - Fast Hash algorithm
|
* xxHash - Fast Hash algorithm
|
||||||
* Copyright (c) 2012-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - xxHash homepage: http://www.xxhash.com
|
* - xxHash homepage: http://www.xxhash.com
|
||||||
|
@ -30,9 +30,7 @@
|
||||||
* Prefer these methods in priority order (0 > 1 > 2)
|
* Prefer these methods in priority order (0 > 1 > 2)
|
||||||
*/
|
*/
|
||||||
#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
#ifndef XXH_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__) )
|
# if (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
||||||
# define XXH_FORCE_MEMORY_ACCESS 2
|
|
||||||
# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
|
|
||||||
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \
|
(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \
|
||||||
defined(__ICCARM__)
|
defined(__ICCARM__)
|
||||||
# define XXH_FORCE_MEMORY_ACCESS 1
|
# define XXH_FORCE_MEMORY_ACCESS 1
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* xxHash - Extremely Fast Hash algorithm
|
* xxHash - Extremely Fast Hash algorithm
|
||||||
* Header File
|
* Header File
|
||||||
* Copyright (c) 2012-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Facebook, Inc.
|
* Copyright (c) Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -36,6 +36,11 @@
|
||||||
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||||
#endif
|
#endif
|
||||||
#include "xxhash.h" /* XXH_reset, update, digest */
|
#include "xxhash.h" /* XXH_reset, update, digest */
|
||||||
|
#ifndef ZSTD_NO_TRACE
|
||||||
|
# include "zstd_trace.h"
|
||||||
|
#else
|
||||||
|
# define ZSTD_TRACE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -347,11 +352,18 @@ typedef enum {
|
||||||
* Private declarations
|
* Private declarations
|
||||||
*********************************************/
|
*********************************************/
|
||||||
typedef struct seqDef_s {
|
typedef struct seqDef_s {
|
||||||
U32 offset; /* Offset code of the sequence */
|
U32 offset; /* offset == rawOffset + ZSTD_REP_NUM, or equivalently, offCode + 1 */
|
||||||
U16 litLength;
|
U16 litLength;
|
||||||
U16 matchLength;
|
U16 matchLength;
|
||||||
} seqDef;
|
} seqDef;
|
||||||
|
|
||||||
|
/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */
|
||||||
|
typedef enum {
|
||||||
|
ZSTD_llt_none = 0, /* no longLengthType */
|
||||||
|
ZSTD_llt_literalLength = 1, /* represents a long literal */
|
||||||
|
ZSTD_llt_matchLength = 2 /* represents a long match */
|
||||||
|
} ZSTD_longLengthType_e;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
seqDef* sequencesStart;
|
seqDef* sequencesStart;
|
||||||
seqDef* sequences; /* ptr to end of sequences */
|
seqDef* sequences; /* ptr to end of sequences */
|
||||||
|
@ -363,12 +375,12 @@ typedef struct {
|
||||||
size_t maxNbSeq;
|
size_t maxNbSeq;
|
||||||
size_t maxNbLit;
|
size_t maxNbLit;
|
||||||
|
|
||||||
/* longLengthPos and longLengthID to allow us to represent either a single litLength or matchLength
|
/* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength
|
||||||
* in the seqStore that has a value larger than U16 (if it exists). To do so, we increment
|
* in the seqStore that has a value larger than U16 (if it exists). To do so, we increment
|
||||||
* the existing value of the litLength or matchLength by 0x10000.
|
* the existing value of the litLength or matchLength by 0x10000.
|
||||||
*/
|
*/
|
||||||
U32 longLengthID; /* 0 == no longLength; 1 == Represent the long literal; 2 == Represent the long match; */
|
ZSTD_longLengthType_e longLengthType;
|
||||||
U32 longLengthPos; /* Index of the sequence to apply long length modification to */
|
U32 longLengthPos; /* Index of the sequence to apply long length modification to */
|
||||||
} seqStore_t;
|
} seqStore_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -378,7 +390,7 @@ typedef struct {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences
|
* Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences
|
||||||
* indicated by longLengthPos and longLengthID, and adds MINMATCH back to matchLength.
|
* indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength.
|
||||||
*/
|
*/
|
||||||
MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq)
|
MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq)
|
||||||
{
|
{
|
||||||
|
@ -386,10 +398,10 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore
|
||||||
seqLen.litLength = seq->litLength;
|
seqLen.litLength = seq->litLength;
|
||||||
seqLen.matchLength = seq->matchLength + MINMATCH;
|
seqLen.matchLength = seq->matchLength + MINMATCH;
|
||||||
if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {
|
if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {
|
||||||
if (seqStore->longLengthID == 1) {
|
if (seqStore->longLengthType == ZSTD_llt_literalLength) {
|
||||||
seqLen.litLength += 0xFFFF;
|
seqLen.litLength += 0xFFFF;
|
||||||
}
|
}
|
||||||
if (seqStore->longLengthID == 2) {
|
if (seqStore->longLengthType == ZSTD_llt_matchLength) {
|
||||||
seqLen.matchLength += 0xFFFF;
|
seqLen.matchLength += 0xFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTD_TRACE_H
|
||||||
|
#define ZSTD_TRACE_H
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* weak symbol support */
|
||||||
|
#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && defined(__GNUC__) && \
|
||||||
|
!defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \
|
||||||
|
!defined(__CYGWIN__)
|
||||||
|
# define ZSTD_HAVE_WEAK_SYMBOLS 1
|
||||||
|
#else
|
||||||
|
# define ZSTD_HAVE_WEAK_SYMBOLS 0
|
||||||
|
#endif
|
||||||
|
#if ZSTD_HAVE_WEAK_SYMBOLS
|
||||||
|
# define ZSTD_WEAK_ATTR __attribute__((__weak__))
|
||||||
|
#else
|
||||||
|
# define ZSTD_WEAK_ATTR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Only enable tracing when weak symbols are available. */
|
||||||
|
#ifndef ZSTD_TRACE
|
||||||
|
# define ZSTD_TRACE ZSTD_HAVE_WEAK_SYMBOLS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ZSTD_TRACE
|
||||||
|
|
||||||
|
struct ZSTD_CCtx_s;
|
||||||
|
struct ZSTD_DCtx_s;
|
||||||
|
struct ZSTD_CCtx_params_s;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* ZSTD_VERSION_NUMBER
|
||||||
|
*
|
||||||
|
* This is guaranteed to be the first member of ZSTD_trace.
|
||||||
|
* Otherwise, this struct is not stable between versions. If
|
||||||
|
* the version number does not match your expectation, you
|
||||||
|
* should not interpret the rest of the struct.
|
||||||
|
*/
|
||||||
|
unsigned version;
|
||||||
|
/**
|
||||||
|
* Non-zero if streaming (de)compression is used.
|
||||||
|
*/
|
||||||
|
unsigned streaming;
|
||||||
|
/**
|
||||||
|
* The dictionary ID.
|
||||||
|
*/
|
||||||
|
unsigned dictionaryID;
|
||||||
|
/**
|
||||||
|
* Is the dictionary cold?
|
||||||
|
* Only set on decompression.
|
||||||
|
*/
|
||||||
|
unsigned dictionaryIsCold;
|
||||||
|
/**
|
||||||
|
* The dictionary size or zero if no dictionary.
|
||||||
|
*/
|
||||||
|
size_t dictionarySize;
|
||||||
|
/**
|
||||||
|
* The uncompressed size of the data.
|
||||||
|
*/
|
||||||
|
size_t uncompressedSize;
|
||||||
|
/**
|
||||||
|
* The compressed size of the data.
|
||||||
|
*/
|
||||||
|
size_t compressedSize;
|
||||||
|
/**
|
||||||
|
* The fully resolved CCtx parameters (NULL on decompression).
|
||||||
|
*/
|
||||||
|
struct ZSTD_CCtx_params_s const* params;
|
||||||
|
/**
|
||||||
|
* The ZSTD_CCtx pointer (NULL on decompression).
|
||||||
|
*/
|
||||||
|
struct ZSTD_CCtx_s const* cctx;
|
||||||
|
/**
|
||||||
|
* The ZSTD_DCtx pointer (NULL on compression).
|
||||||
|
*/
|
||||||
|
struct ZSTD_DCtx_s const* dctx;
|
||||||
|
} ZSTD_Trace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tracing context. It must be 0 when tracing is disabled.
|
||||||
|
* Otherwise, any non-zero value returned by a tracing begin()
|
||||||
|
* function is presented to any subsequent calls to end().
|
||||||
|
*
|
||||||
|
* Any non-zero value is treated as tracing is enabled and not
|
||||||
|
* interpreted by the library.
|
||||||
|
*
|
||||||
|
* Two possible uses are:
|
||||||
|
* * A timestamp for when the begin() function was called.
|
||||||
|
* * A unique key identifying the (de)compression, like the
|
||||||
|
* address of the [dc]ctx pointer if you need to track
|
||||||
|
* more information than just a timestamp.
|
||||||
|
*/
|
||||||
|
typedef unsigned long long ZSTD_TraceCtx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace the beginning of a compression call.
|
||||||
|
* @param cctx The dctx pointer for the compression.
|
||||||
|
* It can be used as a key to map begin() to end().
|
||||||
|
* @returns Non-zero if tracing is enabled. The return value is
|
||||||
|
* passed to ZSTD_trace_compress_end().
|
||||||
|
*/
|
||||||
|
ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_compress_begin(
|
||||||
|
struct ZSTD_CCtx_s const* cctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace the end of a compression call.
|
||||||
|
* @param ctx The return value of ZSTD_trace_compress_begin().
|
||||||
|
* @param trace The zstd tracing info.
|
||||||
|
*/
|
||||||
|
ZSTD_WEAK_ATTR void ZSTD_trace_compress_end(
|
||||||
|
ZSTD_TraceCtx ctx,
|
||||||
|
ZSTD_Trace const* trace);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace the beginning of a decompression call.
|
||||||
|
* @param dctx The dctx pointer for the decompression.
|
||||||
|
* It can be used as a key to map begin() to end().
|
||||||
|
* @returns Non-zero if tracing is enabled. The return value is
|
||||||
|
* passed to ZSTD_trace_compress_end().
|
||||||
|
*/
|
||||||
|
ZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_decompress_begin(
|
||||||
|
struct ZSTD_DCtx_s const* dctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace the end of a decompression call.
|
||||||
|
* @param ctx The return value of ZSTD_trace_decompress_begin().
|
||||||
|
* @param trace The zstd tracing info.
|
||||||
|
*/
|
||||||
|
ZSTD_WEAK_ATTR void ZSTD_trace_decompress_end(
|
||||||
|
ZSTD_TraceCtx ctx,
|
||||||
|
ZSTD_Trace const* trace);
|
||||||
|
|
||||||
|
#endif /* ZSTD_TRACE */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZSTD_TRACE_H */
|
|
@ -1,6 +1,6 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* FSE : Finite State Entropy encoder
|
* FSE : Finite State Entropy encoder
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* hist : Histogram functions
|
* hist : Histogram functions
|
||||||
* part of Finite State Entropy project
|
* part of Finite State Entropy project
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* hist : Histogram functions
|
* hist : Histogram functions
|
||||||
* part of Finite State Entropy project
|
* part of Finite State Entropy project
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* Huffman encoder, part of New Generation Entropy library
|
* Huffman encoder, part of New Generation Entropy library
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
@ -59,7 +59,15 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
|
||||||
* Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
|
* Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.
|
||||||
*/
|
*/
|
||||||
#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
|
#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6
|
||||||
static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)
|
|
||||||
|
typedef struct {
|
||||||
|
FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
|
||||||
|
U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)];
|
||||||
|
unsigned count[HUF_TABLELOG_MAX+1];
|
||||||
|
S16 norm[HUF_TABLELOG_MAX+1];
|
||||||
|
} HUF_CompressWeightsWksp;
|
||||||
|
|
||||||
|
static size_t HUF_compressWeights(void* dst, size_t dstSize, const void* weightTable, size_t wtSize, void* workspace, size_t workspaceSize)
|
||||||
{
|
{
|
||||||
BYTE* const ostart = (BYTE*) dst;
|
BYTE* const ostart = (BYTE*) dst;
|
||||||
BYTE* op = ostart;
|
BYTE* op = ostart;
|
||||||
|
@ -67,33 +75,30 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight
|
||||||
|
|
||||||
unsigned maxSymbolValue = HUF_TABLELOG_MAX;
|
unsigned maxSymbolValue = HUF_TABLELOG_MAX;
|
||||||
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
|
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
|
||||||
|
HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)workspace;
|
||||||
|
|
||||||
FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];
|
if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC);
|
||||||
U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)];
|
|
||||||
|
|
||||||
unsigned count[HUF_TABLELOG_MAX+1];
|
|
||||||
S16 norm[HUF_TABLELOG_MAX+1];
|
|
||||||
|
|
||||||
/* init conditions */
|
/* init conditions */
|
||||||
if (wtSize <= 1) return 0; /* Not compressible */
|
if (wtSize <= 1) return 0; /* Not compressible */
|
||||||
|
|
||||||
/* Scan input and build symbol stats */
|
/* Scan input and build symbol stats */
|
||||||
{ unsigned const maxCount = HIST_count_simple(count, &maxSymbolValue, weightTable, wtSize); /* never fails */
|
{ unsigned const maxCount = HIST_count_simple(wksp->count, &maxSymbolValue, weightTable, wtSize); /* never fails */
|
||||||
if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
|
if (maxCount == wtSize) return 1; /* only a single symbol in src : rle */
|
||||||
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
|
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
|
||||||
}
|
}
|
||||||
|
|
||||||
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
|
tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);
|
||||||
CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) );
|
CHECK_F( FSE_normalizeCount(wksp->norm, tableLog, wksp->count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) );
|
||||||
|
|
||||||
/* Write table description header */
|
/* Write table description header */
|
||||||
{ CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) );
|
{ CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), wksp->norm, maxSymbolValue, tableLog) );
|
||||||
op += hSize;
|
op += hSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compress */
|
/* Compress */
|
||||||
CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) );
|
CHECK_F( FSE_buildCTable_wksp(wksp->CTable, wksp->norm, maxSymbolValue, tableLog, wksp->scratchBuffer, sizeof(wksp->scratchBuffer)) );
|
||||||
{ CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) );
|
{ CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, wksp->CTable) );
|
||||||
if (cSize == 0) return 0; /* not enough space for compressed data */
|
if (cSize == 0) return 0; /* not enough space for compressed data */
|
||||||
op += cSize;
|
op += cSize;
|
||||||
}
|
}
|
||||||
|
@ -102,29 +107,33 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! HUF_writeCTable() :
|
typedef struct {
|
||||||
`CTable` : Huffman tree to save, using huf representation.
|
HUF_CompressWeightsWksp wksp;
|
||||||
@return : size of saved CTable */
|
|
||||||
size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
|
||||||
const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog)
|
|
||||||
{
|
|
||||||
BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
|
BYTE bitsToWeight[HUF_TABLELOG_MAX + 1]; /* precomputed conversion table */
|
||||||
BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
|
BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
|
||||||
|
} HUF_WriteCTableWksp;
|
||||||
|
|
||||||
|
size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,
|
||||||
|
const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog,
|
||||||
|
void* workspace, size_t workspaceSize)
|
||||||
|
{
|
||||||
BYTE* op = (BYTE*)dst;
|
BYTE* op = (BYTE*)dst;
|
||||||
U32 n;
|
U32 n;
|
||||||
|
HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)workspace;
|
||||||
|
|
||||||
/* check conditions */
|
/* check conditions */
|
||||||
|
if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC);
|
||||||
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
|
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
|
||||||
|
|
||||||
/* convert to weight */
|
/* convert to weight */
|
||||||
bitsToWeight[0] = 0;
|
wksp->bitsToWeight[0] = 0;
|
||||||
for (n=1; n<huffLog+1; n++)
|
for (n=1; n<huffLog+1; n++)
|
||||||
bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
|
wksp->bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
|
||||||
for (n=0; n<maxSymbolValue; n++)
|
for (n=0; n<maxSymbolValue; n++)
|
||||||
huffWeight[n] = bitsToWeight[CTable[n].nbBits];
|
wksp->huffWeight[n] = wksp->bitsToWeight[CTable[n].nbBits];
|
||||||
|
|
||||||
/* attempt weights compression by FSE */
|
/* attempt weights compression by FSE */
|
||||||
{ CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, huffWeight, maxSymbolValue) );
|
{ CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, wksp->huffWeight, maxSymbolValue, &wksp->wksp, sizeof(wksp->wksp)) );
|
||||||
if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */
|
if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */
|
||||||
op[0] = (BYTE)hSize;
|
op[0] = (BYTE)hSize;
|
||||||
return hSize+1;
|
return hSize+1;
|
||||||
|
@ -134,12 +143,22 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
||||||
if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */
|
if (maxSymbolValue > (256-128)) return ERROR(GENERIC); /* should not happen : likely means source cannot be compressed */
|
||||||
if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */
|
if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall); /* not enough space within dst buffer */
|
||||||
op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));
|
op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));
|
||||||
huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */
|
wksp->huffWeight[maxSymbolValue] = 0; /* to be sure it doesn't cause msan issue in final combination */
|
||||||
for (n=0; n<maxSymbolValue; n+=2)
|
for (n=0; n<maxSymbolValue; n+=2)
|
||||||
op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);
|
op[(n/2)+1] = (BYTE)((wksp->huffWeight[n] << 4) + wksp->huffWeight[n+1]);
|
||||||
return ((maxSymbolValue+1)/2) + 1;
|
return ((maxSymbolValue+1)/2) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! HUF_writeCTable() :
|
||||||
|
`CTable` : Huffman tree to save, using huf representation.
|
||||||
|
@return : size of saved CTable */
|
||||||
|
size_t HUF_writeCTable (void* dst, size_t maxDstSize,
|
||||||
|
const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog)
|
||||||
|
{
|
||||||
|
HUF_WriteCTableWksp wksp;
|
||||||
|
return HUF_writeCTable_wksp(dst, maxDstSize, CTable, maxSymbolValue, huffLog, &wksp, sizeof(wksp));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights)
|
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights)
|
||||||
{
|
{
|
||||||
|
@ -732,7 +751,10 @@ static size_t HUF_compressCTable_internal(
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned count[HUF_SYMBOLVALUE_MAX + 1];
|
unsigned count[HUF_SYMBOLVALUE_MAX + 1];
|
||||||
HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
|
HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
|
||||||
HUF_buildCTable_wksp_tables buildCTable_wksp;
|
union {
|
||||||
|
HUF_buildCTable_wksp_tables buildCTable_wksp;
|
||||||
|
HUF_WriteCTableWksp writeCTable_wksp;
|
||||||
|
} wksps;
|
||||||
} HUF_compress_tables_t;
|
} HUF_compress_tables_t;
|
||||||
|
|
||||||
/* HUF_compress_internal() :
|
/* HUF_compress_internal() :
|
||||||
|
@ -795,7 +817,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||||
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
|
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
|
||||||
{ size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,
|
{ size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,
|
||||||
maxSymbolValue, huffLog,
|
maxSymbolValue, huffLog,
|
||||||
&table->buildCTable_wksp, sizeof(table->buildCTable_wksp));
|
&table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp));
|
||||||
CHECK_F(maxBits);
|
CHECK_F(maxBits);
|
||||||
huffLog = (U32)maxBits;
|
huffLog = (U32)maxBits;
|
||||||
/* Zero unused symbols in CTable, so we can check it for validity */
|
/* Zero unused symbols in CTable, so we can check it for validity */
|
||||||
|
@ -804,7 +826,8 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write table description header */
|
/* Write table description header */
|
||||||
{ CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) );
|
{ CHECK_V_F(hSize, HUF_writeCTable_wksp(op, dstSize, table->CTable, maxSymbolValue, huffLog,
|
||||||
|
&table->wksps.writeCTable_wksp, sizeof(table->wksps.writeCTable_wksp)) );
|
||||||
/* Check if using previous huffman table is beneficial */
|
/* Check if using previous huffman table is beneficial */
|
||||||
if (repeat && *repeat != HUF_repeat_none) {
|
if (repeat && *repeat != HUF_repeat_none) {
|
||||||
size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);
|
size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -81,6 +81,53 @@ typedef struct {
|
||||||
ZSTD_fseCTables_t fse;
|
ZSTD_fseCTables_t fse;
|
||||||
} ZSTD_entropyCTables_t;
|
} ZSTD_entropyCTables_t;
|
||||||
|
|
||||||
|
/***********************************************
|
||||||
|
* Entropy buffer statistics structs and funcs *
|
||||||
|
***********************************************/
|
||||||
|
/** ZSTD_hufCTablesMetadata_t :
|
||||||
|
* Stores Literals Block Type for a super-block in hType, and
|
||||||
|
* huffman tree description in hufDesBuffer.
|
||||||
|
* hufDesSize refers to the size of huffman tree description in bytes.
|
||||||
|
* This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */
|
||||||
|
typedef struct {
|
||||||
|
symbolEncodingType_e hType;
|
||||||
|
BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
|
||||||
|
size_t hufDesSize;
|
||||||
|
} ZSTD_hufCTablesMetadata_t;
|
||||||
|
|
||||||
|
/** ZSTD_fseCTablesMetadata_t :
|
||||||
|
* Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
|
||||||
|
* fse tables in fseTablesBuffer.
|
||||||
|
* fseTablesSize refers to the size of fse tables in bytes.
|
||||||
|
* This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */
|
||||||
|
typedef struct {
|
||||||
|
symbolEncodingType_e llType;
|
||||||
|
symbolEncodingType_e ofType;
|
||||||
|
symbolEncodingType_e mlType;
|
||||||
|
BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
|
||||||
|
size_t fseTablesSize;
|
||||||
|
size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */
|
||||||
|
} ZSTD_fseCTablesMetadata_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ZSTD_hufCTablesMetadata_t hufMetadata;
|
||||||
|
ZSTD_fseCTablesMetadata_t fseMetadata;
|
||||||
|
} ZSTD_entropyCTablesMetadata_t;
|
||||||
|
|
||||||
|
/** ZSTD_buildBlockEntropyStats() :
|
||||||
|
* Builds entropy for the block.
|
||||||
|
* @return : 0 on success or error code */
|
||||||
|
size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
|
||||||
|
const ZSTD_entropyCTables_t* prevEntropy,
|
||||||
|
ZSTD_entropyCTables_t* nextEntropy,
|
||||||
|
const ZSTD_CCtx_params* cctxParams,
|
||||||
|
ZSTD_entropyCTablesMetadata_t* entropyMetadata,
|
||||||
|
void* workspace, size_t wkspSize);
|
||||||
|
|
||||||
|
/*********************************
|
||||||
|
* Compression internals structs *
|
||||||
|
*********************************/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
|
U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
|
||||||
U32 len; /* Raw length of match */
|
U32 len; /* Raw length of match */
|
||||||
|
@ -141,14 +188,21 @@ typedef struct {
|
||||||
} ZSTD_compressedBlockState_t;
|
} ZSTD_compressedBlockState_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE const* nextSrc; /* next block here to continue on current prefix */
|
BYTE const* nextSrc; /* next block here to continue on current prefix */
|
||||||
BYTE const* base; /* All regular indexes relative to this position */
|
BYTE const* base; /* All regular indexes relative to this position */
|
||||||
BYTE const* dictBase; /* extDict indexes relative to this position */
|
BYTE const* dictBase; /* extDict indexes relative to this position */
|
||||||
U32 dictLimit; /* below that point, need extDict */
|
U32 dictLimit; /* below that point, need extDict */
|
||||||
U32 lowLimit; /* below that point, no more valid data */
|
U32 lowLimit; /* below that point, no more valid data */
|
||||||
|
U32 nbOverflowCorrections; /* Number of times overflow correction has run since
|
||||||
|
* ZSTD_window_init(). Useful for debugging coredumps
|
||||||
|
* and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY.
|
||||||
|
*/
|
||||||
} ZSTD_window_t;
|
} ZSTD_window_t;
|
||||||
|
|
||||||
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
|
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
|
||||||
|
|
||||||
|
#define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */
|
||||||
|
|
||||||
struct ZSTD_matchState_t {
|
struct ZSTD_matchState_t {
|
||||||
ZSTD_window_t window; /* State for window round buffer management */
|
ZSTD_window_t window; /* State for window round buffer management */
|
||||||
U32 loadedDictEnd; /* index of end of dictionary, within context's referential.
|
U32 loadedDictEnd; /* index of end of dictionary, within context's referential.
|
||||||
|
@ -160,9 +214,17 @@ struct ZSTD_matchState_t {
|
||||||
*/
|
*/
|
||||||
U32 nextToUpdate; /* index from which to continue table update */
|
U32 nextToUpdate; /* index from which to continue table update */
|
||||||
U32 hashLog3; /* dispatch table for matches of len==3 : larger == faster, more memory */
|
U32 hashLog3; /* dispatch table for matches of len==3 : larger == faster, more memory */
|
||||||
|
|
||||||
|
U32 rowHashLog; /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/
|
||||||
|
U16* tagTable; /* For row-based matchFinder: A row-based table containing the hashes and head index. */
|
||||||
|
U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */
|
||||||
|
|
||||||
U32* hashTable;
|
U32* hashTable;
|
||||||
U32* hashTable3;
|
U32* hashTable3;
|
||||||
U32* chainTable;
|
U32* chainTable;
|
||||||
|
|
||||||
|
U32 forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */
|
||||||
|
|
||||||
int dedicatedDictSearch; /* Indicates whether this matchState is using the
|
int dedicatedDictSearch; /* Indicates whether this matchState is using the
|
||||||
* dedicated dictionary search structure.
|
* dedicated dictionary search structure.
|
||||||
*/
|
*/
|
||||||
|
@ -183,13 +245,22 @@ typedef struct {
|
||||||
U32 checksum;
|
U32 checksum;
|
||||||
} ldmEntry_t;
|
} ldmEntry_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BYTE const* split;
|
||||||
|
U32 hash;
|
||||||
|
U32 checksum;
|
||||||
|
ldmEntry_t* bucket;
|
||||||
|
} ldmMatchCandidate_t;
|
||||||
|
|
||||||
|
#define LDM_BATCH_SIZE 64
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ZSTD_window_t window; /* State for the window round buffer management */
|
ZSTD_window_t window; /* State for the window round buffer management */
|
||||||
ldmEntry_t* hashTable;
|
ldmEntry_t* hashTable;
|
||||||
U32 loadedDictEnd;
|
U32 loadedDictEnd;
|
||||||
BYTE* bucketOffsets; /* Next position in bucket to insert entry */
|
BYTE* bucketOffsets; /* Next position in bucket to insert entry */
|
||||||
U64 hashPower; /* Used to compute the rolling hash.
|
size_t splitIndices[LDM_BATCH_SIZE];
|
||||||
* Depends on ldmParams.minMatchLength */
|
ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE];
|
||||||
} ldmState_t;
|
} ldmState_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -246,6 +317,15 @@ struct ZSTD_CCtx_params_s {
|
||||||
ZSTD_sequenceFormat_e blockDelimiters;
|
ZSTD_sequenceFormat_e blockDelimiters;
|
||||||
int validateSequences;
|
int validateSequences;
|
||||||
|
|
||||||
|
/* Block splitting */
|
||||||
|
int splitBlocks;
|
||||||
|
|
||||||
|
/* Param for deciding whether to use row-based matchfinder */
|
||||||
|
ZSTD_useRowMatchFinderMode_e useRowMatchFinder;
|
||||||
|
|
||||||
|
/* Always load a dictionary in ext-dict mode (not prefix mode)? */
|
||||||
|
int deterministicRefPrefix;
|
||||||
|
|
||||||
/* Internal use, for createCCtxParams() and freeCCtxParams() only */
|
/* Internal use, for createCCtxParams() and freeCCtxParams() only */
|
||||||
ZSTD_customMem customMem;
|
ZSTD_customMem customMem;
|
||||||
}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
|
}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
|
||||||
|
@ -269,7 +349,9 @@ struct ZSTD_CCtx_s {
|
||||||
int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
|
int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
|
||||||
ZSTD_CCtx_params requestedParams;
|
ZSTD_CCtx_params requestedParams;
|
||||||
ZSTD_CCtx_params appliedParams;
|
ZSTD_CCtx_params appliedParams;
|
||||||
|
ZSTD_CCtx_params simpleApiParams; /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */
|
||||||
U32 dictID;
|
U32 dictID;
|
||||||
|
size_t dictContentSize;
|
||||||
|
|
||||||
ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */
|
ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */
|
||||||
size_t blockSize;
|
size_t blockSize;
|
||||||
|
@ -321,6 +403,11 @@ struct ZSTD_CCtx_s {
|
||||||
#ifdef ZSTD_MULTITHREAD
|
#ifdef ZSTD_MULTITHREAD
|
||||||
ZSTDMT_CCtx* mtctx;
|
ZSTDMT_CCtx* mtctx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Tracing */
|
||||||
|
#if ZSTD_TRACE
|
||||||
|
ZSTD_TraceCtx traceCtx;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
|
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
|
||||||
|
@ -355,7 +442,7 @@ typedef enum {
|
||||||
typedef size_t (*ZSTD_blockCompressor) (
|
typedef size_t (*ZSTD_blockCompressor) (
|
||||||
ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize);
|
void const* src, size_t srcSize);
|
||||||
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode);
|
ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
|
||||||
|
|
||||||
|
|
||||||
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
|
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
|
||||||
|
@ -532,8 +619,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
|
||||||
|
|
||||||
/* literal Length */
|
/* literal Length */
|
||||||
if (litLength>0xFFFF) {
|
if (litLength>0xFFFF) {
|
||||||
assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
|
assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
|
||||||
seqStorePtr->longLengthID = 1;
|
seqStorePtr->longLengthType = ZSTD_llt_literalLength;
|
||||||
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||||
}
|
}
|
||||||
seqStorePtr->sequences[0].litLength = (U16)litLength;
|
seqStorePtr->sequences[0].litLength = (U16)litLength;
|
||||||
|
@ -543,8 +630,8 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
|
||||||
|
|
||||||
/* match Length */
|
/* match Length */
|
||||||
if (mlBase>0xFFFF) {
|
if (mlBase>0xFFFF) {
|
||||||
assert(seqStorePtr->longLengthID == 0); /* there can only be a single long length */
|
assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
|
||||||
seqStorePtr->longLengthID = 2;
|
seqStorePtr->longLengthType = ZSTD_llt_matchLength;
|
||||||
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||||
}
|
}
|
||||||
seqStorePtr->sequences[0].matchLength = (U16)mlBase;
|
seqStorePtr->sequences[0].matchLength = (U16)mlBase;
|
||||||
|
@ -795,6 +882,13 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
|
||||||
window->dictLimit = end;
|
window->dictLimit = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)
|
||||||
|
{
|
||||||
|
return window.dictLimit == 1 &&
|
||||||
|
window.lowLimit == 1 &&
|
||||||
|
(window.nextSrc - window.base) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZSTD_window_hasExtDict():
|
* ZSTD_window_hasExtDict():
|
||||||
* Returns non-zero if the window has a non-empty extDict.
|
* Returns non-zero if the window has a non-empty extDict.
|
||||||
|
@ -818,15 +912,69 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms)
|
||||||
ZSTD_noDict;
|
ZSTD_noDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Defining this macro to non-zero tells zstd to run the overflow correction
|
||||||
|
* code much more frequently. This is very inefficient, and should only be
|
||||||
|
* used for tests and fuzzers.
|
||||||
|
*/
|
||||||
|
#ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY
|
||||||
|
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||||
|
# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1
|
||||||
|
# else
|
||||||
|
# define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ZSTD_window_canOverflowCorrect():
|
||||||
|
* Returns non-zero if the indices are large enough for overflow correction
|
||||||
|
* to work correctly without impacting compression ratio.
|
||||||
|
*/
|
||||||
|
MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,
|
||||||
|
U32 cycleLog,
|
||||||
|
U32 maxDist,
|
||||||
|
U32 loadedDictEnd,
|
||||||
|
void const* src)
|
||||||
|
{
|
||||||
|
U32 const cycleSize = 1u << cycleLog;
|
||||||
|
U32 const curr = (U32)((BYTE const*)src - window.base);
|
||||||
|
U32 const minIndexToOverflowCorrect = cycleSize + MAX(maxDist, cycleSize);
|
||||||
|
|
||||||
|
/* Adjust the min index to backoff the overflow correction frequency,
|
||||||
|
* so we don't waste too much CPU in overflow correction. If this
|
||||||
|
* computation overflows we don't really care, we just need to make
|
||||||
|
* sure it is at least minIndexToOverflowCorrect.
|
||||||
|
*/
|
||||||
|
U32 const adjustment = window.nbOverflowCorrections + 1;
|
||||||
|
U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment,
|
||||||
|
minIndexToOverflowCorrect);
|
||||||
|
U32 const indexLargeEnough = curr > adjustedIndex;
|
||||||
|
|
||||||
|
/* Only overflow correct early if the dictionary is invalidated already,
|
||||||
|
* so we don't hurt compression ratio.
|
||||||
|
*/
|
||||||
|
U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd;
|
||||||
|
|
||||||
|
return indexLargeEnough && dictionaryInvalidated;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ZSTD_window_needOverflowCorrection():
|
* ZSTD_window_needOverflowCorrection():
|
||||||
* Returns non-zero if the indices are getting too large and need overflow
|
* Returns non-zero if the indices are getting too large and need overflow
|
||||||
* protection.
|
* protection.
|
||||||
*/
|
*/
|
||||||
MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
|
MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
|
||||||
|
U32 cycleLog,
|
||||||
|
U32 maxDist,
|
||||||
|
U32 loadedDictEnd,
|
||||||
|
void const* src,
|
||||||
void const* srcEnd)
|
void const* srcEnd)
|
||||||
{
|
{
|
||||||
U32 const curr = (U32)((BYTE const*)srcEnd - window.base);
|
U32 const curr = (U32)((BYTE const*)srcEnd - window.base);
|
||||||
|
if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
|
||||||
|
if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
return curr > ZSTD_CURRENT_MAX;
|
return curr > ZSTD_CURRENT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,7 +986,6 @@ MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,
|
||||||
*
|
*
|
||||||
* The least significant cycleLog bits of the indices must remain the same,
|
* The least significant cycleLog bits of the indices must remain the same,
|
||||||
* which may be 0. Every index up to maxDist in the past must be valid.
|
* which may be 0. Every index up to maxDist in the past must be valid.
|
||||||
* NOTE: (maxDist & cycleMask) must be zero.
|
|
||||||
*/
|
*/
|
||||||
MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||||
U32 maxDist, void const* src)
|
U32 maxDist, void const* src)
|
||||||
|
@ -862,17 +1009,25 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||||
* 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
|
* 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:
|
||||||
* windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
|
* windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.
|
||||||
*/
|
*/
|
||||||
U32 const cycleMask = (1U << cycleLog) - 1;
|
U32 const cycleSize = 1u << cycleLog;
|
||||||
|
U32 const cycleMask = cycleSize - 1;
|
||||||
U32 const curr = (U32)((BYTE const*)src - window->base);
|
U32 const curr = (U32)((BYTE const*)src - window->base);
|
||||||
U32 const currentCycle0 = curr & cycleMask;
|
U32 const currentCycle0 = curr & cycleMask;
|
||||||
/* Exclude zero so that newCurrent - maxDist >= 1. */
|
/* Exclude zero so that newCurrent - maxDist >= 1. */
|
||||||
U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0;
|
U32 const currentCycle1 = currentCycle0 == 0 ? cycleSize : currentCycle0;
|
||||||
U32 const newCurrent = currentCycle1 + maxDist;
|
U32 const newCurrent = currentCycle1 + MAX(maxDist, cycleSize);
|
||||||
U32 const correction = curr - newCurrent;
|
U32 const correction = curr - newCurrent;
|
||||||
assert((maxDist & cycleMask) == 0);
|
/* maxDist must be a power of two so that:
|
||||||
|
* (newCurrent & cycleMask) == (curr & cycleMask)
|
||||||
|
* This is required to not corrupt the chains / binary tree.
|
||||||
|
*/
|
||||||
|
assert((maxDist & (maxDist - 1)) == 0);
|
||||||
|
assert((curr & cycleMask) == (newCurrent & cycleMask));
|
||||||
assert(curr > newCurrent);
|
assert(curr > newCurrent);
|
||||||
/* Loose bound, should be around 1<<29 (see above) */
|
if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {
|
||||||
assert(correction > 1<<28);
|
/* Loose bound, should be around 1<<29 (see above) */
|
||||||
|
assert(correction > 1<<28);
|
||||||
|
}
|
||||||
|
|
||||||
window->base += correction;
|
window->base += correction;
|
||||||
window->dictBase += correction;
|
window->dictBase += correction;
|
||||||
|
@ -888,6 +1043,8 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
|
||||||
assert(window->lowLimit <= newCurrent);
|
assert(window->lowLimit <= newCurrent);
|
||||||
assert(window->dictLimit <= newCurrent);
|
assert(window->dictLimit <= newCurrent);
|
||||||
|
|
||||||
|
++window->nbOverflowCorrections;
|
||||||
|
|
||||||
DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
|
DEBUGLOG(4, "Correction of 0x%x bytes to lowLimit=0x%x", correction,
|
||||||
window->lowLimit);
|
window->lowLimit);
|
||||||
return correction;
|
return correction;
|
||||||
|
@ -997,6 +1154,7 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
|
||||||
window->dictLimit = 1; /* start from 1, so that 1st position is valid */
|
window->dictLimit = 1; /* start from 1, so that 1st position is valid */
|
||||||
window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
|
window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
|
||||||
window->nextSrc = window->base + 1; /* see issue #1241 */
|
window->nextSrc = window->base + 1; /* see issue #1241 */
|
||||||
|
window->nbOverflowCorrections = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1007,7 +1165,8 @@ MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
|
||||||
* Returns non-zero if the segment is contiguous.
|
* Returns non-zero if the segment is contiguous.
|
||||||
*/
|
*/
|
||||||
MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
||||||
void const* src, size_t srcSize)
|
void const* src, size_t srcSize,
|
||||||
|
int forceNonContiguous)
|
||||||
{
|
{
|
||||||
BYTE const* const ip = (BYTE const*)src;
|
BYTE const* const ip = (BYTE const*)src;
|
||||||
U32 contiguous = 1;
|
U32 contiguous = 1;
|
||||||
|
@ -1017,7 +1176,7 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
|
||||||
assert(window->base != NULL);
|
assert(window->base != NULL);
|
||||||
assert(window->dictBase != NULL);
|
assert(window->dictBase != NULL);
|
||||||
/* Check if blocks follow each other */
|
/* Check if blocks follow each other */
|
||||||
if (src != window->nextSrc) {
|
if (src != window->nextSrc || forceNonContiguous) {
|
||||||
/* not contiguous */
|
/* not contiguous */
|
||||||
size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
|
size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);
|
||||||
DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
|
DEBUGLOG(5, "Non contiguous blocks, new segment starts at %u", window->dictLimit);
|
||||||
|
@ -1200,4 +1359,9 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe
|
||||||
* condition for correct operation : hashLog > 1 */
|
* condition for correct operation : hashLog > 1 */
|
||||||
U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
|
U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
|
||||||
|
|
||||||
|
/** ZSTD_CCtx_trace() :
|
||||||
|
* Trace the end of a compression call.
|
||||||
|
*/
|
||||||
|
void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);
|
||||||
|
|
||||||
#endif /* ZSTD_COMPRESS_H */
|
#endif /* ZSTD_COMPRESS_H */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
BYTE* const ostart = (BYTE* const)dst;
|
BYTE* const ostart = (BYTE*)dst;
|
||||||
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||||
|
|
||||||
RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, "");
|
RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, "");
|
||||||
|
@ -42,7 +42,7 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src,
|
||||||
|
|
||||||
size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
BYTE* const ostart = (BYTE* const)dst;
|
BYTE* const ostart = (BYTE*)dst;
|
||||||
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||||
|
|
||||||
(void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
|
(void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
|
||||||
|
@ -117,7 +117,7 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) {
|
if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) {
|
||||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
||||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -85,6 +85,8 @@ static size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t
|
||||||
{
|
{
|
||||||
unsigned cost = 0;
|
unsigned cost = 0;
|
||||||
unsigned s;
|
unsigned s;
|
||||||
|
|
||||||
|
assert(total > 0);
|
||||||
for (s = 0; s <= max; ++s) {
|
for (s = 0; s <= max; ++s) {
|
||||||
unsigned norm = (unsigned)((256 * count[s]) / total);
|
unsigned norm = (unsigned)((256 * count[s]) / total);
|
||||||
if (count[s] != 0 && norm == 0)
|
if (count[s] != 0 && norm == 0)
|
||||||
|
@ -232,6 +234,11 @@ ZSTD_selectEncodingType(
|
||||||
return set_compressed;
|
return set_compressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
S16 norm[MaxSeq + 1];
|
||||||
|
U32 wksp[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(MaxSeq, MaxFSELog)];
|
||||||
|
} ZSTD_BuildCTableWksp;
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
||||||
FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
|
FSE_CTable* nextCTable, U32 FSELog, symbolEncodingType_e type,
|
||||||
|
@ -258,7 +265,7 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
||||||
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */
|
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */
|
||||||
return 0;
|
return 0;
|
||||||
case set_compressed: {
|
case set_compressed: {
|
||||||
S16 norm[MaxSeq + 1];
|
ZSTD_BuildCTableWksp* wksp = (ZSTD_BuildCTableWksp*)entropyWorkspace;
|
||||||
size_t nbSeq_1 = nbSeq;
|
size_t nbSeq_1 = nbSeq;
|
||||||
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);
|
||||||
if (count[codeTable[nbSeq-1]] > 1) {
|
if (count[codeTable[nbSeq-1]] > 1) {
|
||||||
|
@ -266,11 +273,12 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
|
||||||
nbSeq_1--;
|
nbSeq_1--;
|
||||||
}
|
}
|
||||||
assert(nbSeq_1 > 1);
|
assert(nbSeq_1 > 1);
|
||||||
assert(entropyWorkspaceSize >= FSE_BUILD_CTABLE_WORKSPACE_SIZE(MaxSeq, MaxFSELog));
|
assert(entropyWorkspaceSize >= sizeof(ZSTD_BuildCTableWksp));
|
||||||
FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "");
|
(void)entropyWorkspaceSize;
|
||||||
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */
|
FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "");
|
||||||
|
{ size_t const NCountSize = FSE_writeNCount(op, oend - op, wksp->norm, max, tableLog); /* overflow protected */
|
||||||
FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed");
|
FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed");
|
||||||
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), "");
|
FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), "");
|
||||||
return NCountSize;
|
return NCountSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -15,288 +15,10 @@
|
||||||
|
|
||||||
#include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */
|
#include "../common/zstd_internal.h" /* ZSTD_getSequenceLength */
|
||||||
#include "hist.h" /* HIST_countFast_wksp */
|
#include "hist.h" /* HIST_countFast_wksp */
|
||||||
#include "zstd_compress_internal.h"
|
#include "zstd_compress_internal.h" /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */
|
||||||
#include "zstd_compress_sequences.h"
|
#include "zstd_compress_sequences.h"
|
||||||
#include "zstd_compress_literals.h"
|
#include "zstd_compress_literals.h"
|
||||||
|
|
||||||
/*-*************************************
|
|
||||||
* Superblock entropy buffer structs
|
|
||||||
***************************************/
|
|
||||||
/** ZSTD_hufCTablesMetadata_t :
|
|
||||||
* Stores Literals Block Type for a super-block in hType, and
|
|
||||||
* huffman tree description in hufDesBuffer.
|
|
||||||
* hufDesSize refers to the size of huffman tree description in bytes.
|
|
||||||
* This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */
|
|
||||||
typedef struct {
|
|
||||||
symbolEncodingType_e hType;
|
|
||||||
BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];
|
|
||||||
size_t hufDesSize;
|
|
||||||
} ZSTD_hufCTablesMetadata_t;
|
|
||||||
|
|
||||||
/** ZSTD_fseCTablesMetadata_t :
|
|
||||||
* Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and
|
|
||||||
* fse tables in fseTablesBuffer.
|
|
||||||
* fseTablesSize refers to the size of fse tables in bytes.
|
|
||||||
* This metadata is populated in ZSTD_buildSuperBlockEntropy_sequences() */
|
|
||||||
typedef struct {
|
|
||||||
symbolEncodingType_e llType;
|
|
||||||
symbolEncodingType_e ofType;
|
|
||||||
symbolEncodingType_e mlType;
|
|
||||||
BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];
|
|
||||||
size_t fseTablesSize;
|
|
||||||
size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */
|
|
||||||
} ZSTD_fseCTablesMetadata_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ZSTD_hufCTablesMetadata_t hufMetadata;
|
|
||||||
ZSTD_fseCTablesMetadata_t fseMetadata;
|
|
||||||
} ZSTD_entropyCTablesMetadata_t;
|
|
||||||
|
|
||||||
|
|
||||||
/** ZSTD_buildSuperBlockEntropy_literal() :
|
|
||||||
* Builds entropy for the super-block literals.
|
|
||||||
* Stores literals block type (raw, rle, compressed, repeat) and
|
|
||||||
* huffman description table to hufMetadata.
|
|
||||||
* @return : size of huffman description table or error code */
|
|
||||||
static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSize,
|
|
||||||
const ZSTD_hufCTables_t* prevHuf,
|
|
||||||
ZSTD_hufCTables_t* nextHuf,
|
|
||||||
ZSTD_hufCTablesMetadata_t* hufMetadata,
|
|
||||||
const int disableLiteralsCompression,
|
|
||||||
void* workspace, size_t wkspSize)
|
|
||||||
{
|
|
||||||
BYTE* const wkspStart = (BYTE*)workspace;
|
|
||||||
BYTE* const wkspEnd = wkspStart + wkspSize;
|
|
||||||
BYTE* const countWkspStart = wkspStart;
|
|
||||||
unsigned* const countWksp = (unsigned*)workspace;
|
|
||||||
const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);
|
|
||||||
BYTE* const nodeWksp = countWkspStart + countWkspSize;
|
|
||||||
const size_t nodeWkspSize = wkspEnd-nodeWksp;
|
|
||||||
unsigned maxSymbolValue = 255;
|
|
||||||
unsigned huffLog = HUF_TABLELOG_DEFAULT;
|
|
||||||
HUF_repeat repeat = prevHuf->repeatMode;
|
|
||||||
|
|
||||||
DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize);
|
|
||||||
|
|
||||||
/* Prepare nextEntropy assuming reusing the existing table */
|
|
||||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
||||||
|
|
||||||
if (disableLiteralsCompression) {
|
|
||||||
DEBUGLOG(5, "set_basic - disabled");
|
|
||||||
hufMetadata->hType = set_basic;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* small ? don't even attempt compression (speed opt) */
|
|
||||||
# define COMPRESS_LITERALS_SIZE_MIN 63
|
|
||||||
{ size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;
|
|
||||||
if (srcSize <= minLitSize) {
|
|
||||||
DEBUGLOG(5, "set_basic - too small");
|
|
||||||
hufMetadata->hType = set_basic;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Scan input and build symbol stats */
|
|
||||||
{ size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)src, srcSize, workspace, wkspSize);
|
|
||||||
FORWARD_IF_ERROR(largest, "HIST_count_wksp failed");
|
|
||||||
if (largest == srcSize) {
|
|
||||||
DEBUGLOG(5, "set_rle");
|
|
||||||
hufMetadata->hType = set_rle;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (largest <= (srcSize >> 7)+4) {
|
|
||||||
DEBUGLOG(5, "set_basic - no gain");
|
|
||||||
hufMetadata->hType = set_basic;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate the previous Huffman table */
|
|
||||||
if (repeat == HUF_repeat_check && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) {
|
|
||||||
repeat = HUF_repeat_none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build Huffman Tree */
|
|
||||||
ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));
|
|
||||||
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);
|
|
||||||
{ size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,
|
|
||||||
maxSymbolValue, huffLog,
|
|
||||||
nodeWksp, nodeWkspSize);
|
|
||||||
FORWARD_IF_ERROR(maxBits, "HUF_buildCTable_wksp");
|
|
||||||
huffLog = (U32)maxBits;
|
|
||||||
{ /* Build and write the CTable */
|
|
||||||
size_t const newCSize = HUF_estimateCompressedSize(
|
|
||||||
(HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);
|
|
||||||
size_t const hSize = HUF_writeCTable(
|
|
||||||
hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
|
|
||||||
(HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog);
|
|
||||||
/* Check against repeating the previous CTable */
|
|
||||||
if (repeat != HUF_repeat_none) {
|
|
||||||
size_t const oldCSize = HUF_estimateCompressedSize(
|
|
||||||
(HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);
|
|
||||||
if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {
|
|
||||||
DEBUGLOG(5, "set_repeat - smaller");
|
|
||||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
||||||
hufMetadata->hType = set_repeat;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newCSize + hSize >= srcSize) {
|
|
||||||
DEBUGLOG(5, "set_basic - no gains");
|
|
||||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
|
||||||
hufMetadata->hType = set_basic;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize);
|
|
||||||
hufMetadata->hType = set_compressed;
|
|
||||||
nextHuf->repeatMode = HUF_repeat_check;
|
|
||||||
return hSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ZSTD_buildSuperBlockEntropy_sequences() :
|
|
||||||
* Builds entropy for the super-block sequences.
|
|
||||||
* Stores symbol compression modes and fse table to fseMetadata.
|
|
||||||
* @return : size of fse tables or error code */
|
|
||||||
static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr,
|
|
||||||
const ZSTD_fseCTables_t* prevEntropy,
|
|
||||||
ZSTD_fseCTables_t* nextEntropy,
|
|
||||||
const ZSTD_CCtx_params* cctxParams,
|
|
||||||
ZSTD_fseCTablesMetadata_t* fseMetadata,
|
|
||||||
void* workspace, size_t wkspSize)
|
|
||||||
{
|
|
||||||
BYTE* const wkspStart = (BYTE*)workspace;
|
|
||||||
BYTE* const wkspEnd = wkspStart + wkspSize;
|
|
||||||
BYTE* const countWkspStart = wkspStart;
|
|
||||||
unsigned* const countWksp = (unsigned*)workspace;
|
|
||||||
const size_t countWkspSize = (MaxSeq + 1) * sizeof(unsigned);
|
|
||||||
BYTE* const cTableWksp = countWkspStart + countWkspSize;
|
|
||||||
const size_t cTableWkspSize = wkspEnd-cTableWksp;
|
|
||||||
ZSTD_strategy const strategy = cctxParams->cParams.strategy;
|
|
||||||
FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;
|
|
||||||
FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;
|
|
||||||
FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;
|
|
||||||
const BYTE* const ofCodeTable = seqStorePtr->ofCode;
|
|
||||||
const BYTE* const llCodeTable = seqStorePtr->llCode;
|
|
||||||
const BYTE* const mlCodeTable = seqStorePtr->mlCode;
|
|
||||||
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
|
||||||
BYTE* const ostart = fseMetadata->fseTablesBuffer;
|
|
||||||
BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
|
|
||||||
BYTE* op = ostart;
|
|
||||||
|
|
||||||
assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE));
|
|
||||||
DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq);
|
|
||||||
ZSTD_memset(workspace, 0, wkspSize);
|
|
||||||
|
|
||||||
fseMetadata->lastCountSize = 0;
|
|
||||||
/* convert length/distances into codes */
|
|
||||||
ZSTD_seqToCodes(seqStorePtr);
|
|
||||||
/* build CTable for Literal Lengths */
|
|
||||||
{ U32 LLtype;
|
|
||||||
unsigned max = MaxLL;
|
|
||||||
size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, llCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
|
|
||||||
DEBUGLOG(5, "Building LL table");
|
|
||||||
nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;
|
|
||||||
LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,
|
|
||||||
countWksp, max, mostFrequent, nbSeq,
|
|
||||||
LLFSELog, prevEntropy->litlengthCTable,
|
|
||||||
LL_defaultNorm, LL_defaultNormLog,
|
|
||||||
ZSTD_defaultAllowed, strategy);
|
|
||||||
assert(set_basic < set_compressed && set_rle < set_compressed);
|
|
||||||
assert(!(LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
||||||
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_LitLength, LLFSELog, (symbolEncodingType_e)LLtype,
|
|
||||||
countWksp, max, llCodeTable, nbSeq, LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
|
||||||
prevEntropy->litlengthCTable, sizeof(prevEntropy->litlengthCTable),
|
|
||||||
cTableWksp, cTableWkspSize);
|
|
||||||
FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for LitLens failed");
|
|
||||||
if (LLtype == set_compressed)
|
|
||||||
fseMetadata->lastCountSize = countSize;
|
|
||||||
op += countSize;
|
|
||||||
fseMetadata->llType = (symbolEncodingType_e) LLtype;
|
|
||||||
} }
|
|
||||||
/* build CTable for Offsets */
|
|
||||||
{ U32 Offtype;
|
|
||||||
unsigned max = MaxOff;
|
|
||||||
size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, ofCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
|
|
||||||
/* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */
|
|
||||||
ZSTD_defaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;
|
|
||||||
DEBUGLOG(5, "Building OF table");
|
|
||||||
nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;
|
|
||||||
Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,
|
|
||||||
countWksp, max, mostFrequent, nbSeq,
|
|
||||||
OffFSELog, prevEntropy->offcodeCTable,
|
|
||||||
OF_defaultNorm, OF_defaultNormLog,
|
|
||||||
defaultPolicy, strategy);
|
|
||||||
assert(!(Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
||||||
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_OffsetBits, OffFSELog, (symbolEncodingType_e)Offtype,
|
|
||||||
countWksp, max, ofCodeTable, nbSeq, OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
|
||||||
prevEntropy->offcodeCTable, sizeof(prevEntropy->offcodeCTable),
|
|
||||||
cTableWksp, cTableWkspSize);
|
|
||||||
FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for Offsets failed");
|
|
||||||
if (Offtype == set_compressed)
|
|
||||||
fseMetadata->lastCountSize = countSize;
|
|
||||||
op += countSize;
|
|
||||||
fseMetadata->ofType = (symbolEncodingType_e) Offtype;
|
|
||||||
} }
|
|
||||||
/* build CTable for MatchLengths */
|
|
||||||
{ U32 MLtype;
|
|
||||||
unsigned max = MaxML;
|
|
||||||
size_t const mostFrequent = HIST_countFast_wksp(countWksp, &max, mlCodeTable, nbSeq, workspace, wkspSize); /* can't fail */
|
|
||||||
DEBUGLOG(5, "Building ML table (remaining space : %i)", (int)(oend-op));
|
|
||||||
nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;
|
|
||||||
MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,
|
|
||||||
countWksp, max, mostFrequent, nbSeq,
|
|
||||||
MLFSELog, prevEntropy->matchlengthCTable,
|
|
||||||
ML_defaultNorm, ML_defaultNormLog,
|
|
||||||
ZSTD_defaultAllowed, strategy);
|
|
||||||
assert(!(MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */
|
|
||||||
{ size_t const countSize = ZSTD_buildCTable(op, oend - op, CTable_MatchLength, MLFSELog, (symbolEncodingType_e)MLtype,
|
|
||||||
countWksp, max, mlCodeTable, nbSeq, ML_defaultNorm, ML_defaultNormLog, MaxML,
|
|
||||||
prevEntropy->matchlengthCTable, sizeof(prevEntropy->matchlengthCTable),
|
|
||||||
cTableWksp, cTableWkspSize);
|
|
||||||
FORWARD_IF_ERROR(countSize, "ZSTD_buildCTable for MatchLengths failed");
|
|
||||||
if (MLtype == set_compressed)
|
|
||||||
fseMetadata->lastCountSize = countSize;
|
|
||||||
op += countSize;
|
|
||||||
fseMetadata->mlType = (symbolEncodingType_e) MLtype;
|
|
||||||
} }
|
|
||||||
assert((size_t) (op-ostart) <= sizeof(fseMetadata->fseTablesBuffer));
|
|
||||||
return op-ostart;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** ZSTD_buildSuperBlockEntropy() :
|
|
||||||
* Builds entropy for the super-block.
|
|
||||||
* @return : 0 on success or error code */
|
|
||||||
static size_t
|
|
||||||
ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
|
|
||||||
const ZSTD_entropyCTables_t* prevEntropy,
|
|
||||||
ZSTD_entropyCTables_t* nextEntropy,
|
|
||||||
const ZSTD_CCtx_params* cctxParams,
|
|
||||||
ZSTD_entropyCTablesMetadata_t* entropyMetadata,
|
|
||||||
void* workspace, size_t wkspSize)
|
|
||||||
{
|
|
||||||
size_t const litSize = seqStorePtr->lit - seqStorePtr->litStart;
|
|
||||||
DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy");
|
|
||||||
entropyMetadata->hufMetadata.hufDesSize =
|
|
||||||
ZSTD_buildSuperBlockEntropy_literal(seqStorePtr->litStart, litSize,
|
|
||||||
&prevEntropy->huf, &nextEntropy->huf,
|
|
||||||
&entropyMetadata->hufMetadata,
|
|
||||||
ZSTD_disableLiteralsCompression(cctxParams),
|
|
||||||
workspace, wkspSize);
|
|
||||||
FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildSuperBlockEntropy_literal failed");
|
|
||||||
entropyMetadata->fseMetadata.fseTablesSize =
|
|
||||||
ZSTD_buildSuperBlockEntropy_sequences(seqStorePtr,
|
|
||||||
&prevEntropy->fse, &nextEntropy->fse,
|
|
||||||
cctxParams,
|
|
||||||
&entropyMetadata->fseMetadata,
|
|
||||||
workspace, wkspSize);
|
|
||||||
FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, "ZSTD_buildSuperBlockEntropy_sequences failed");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ZSTD_compressSubBlock_literal() :
|
/** ZSTD_compressSubBlock_literal() :
|
||||||
* Compresses literals section for a sub-block.
|
* Compresses literals section for a sub-block.
|
||||||
* When we have to write the Huffman table we will sometimes choose a header
|
* When we have to write the Huffman table we will sometimes choose a header
|
||||||
|
@ -304,7 +26,7 @@ ZSTD_buildSuperBlockEntropy(seqStore_t* seqStorePtr,
|
||||||
* before we know the table size + compressed size, so we have a bound on the
|
* before we know the table size + compressed size, so we have a bound on the
|
||||||
* table size. If we guessed incorrectly, we fall back to uncompressed literals.
|
* table size. If we guessed incorrectly, we fall back to uncompressed literals.
|
||||||
*
|
*
|
||||||
* We write the header when writeEntropy=1 and set entropyWrriten=1 when we succeeded
|
* We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded
|
||||||
* in writing the header, otherwise it is set to 0.
|
* in writing the header, otherwise it is set to 0.
|
||||||
*
|
*
|
||||||
* hufMetadata->hType has literals block type info.
|
* hufMetadata->hType has literals block type info.
|
||||||
|
@ -643,8 +365,9 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,
|
||||||
void* workspace, size_t wkspSize,
|
void* workspace, size_t wkspSize,
|
||||||
int writeEntropy)
|
int writeEntropy)
|
||||||
{
|
{
|
||||||
size_t sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
|
size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */
|
||||||
size_t cSeqSizeEstimate = 0;
|
size_t cSeqSizeEstimate = 0;
|
||||||
|
if (nbSeq == 0) return sequencesSectionHeaderSize;
|
||||||
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
|
cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,
|
||||||
nbSeq, fseTables->offcodeCTable, NULL,
|
nbSeq, fseTables->offcodeCTable, NULL,
|
||||||
OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
||||||
|
@ -830,7 +553,7 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,
|
||||||
unsigned lastBlock) {
|
unsigned lastBlock) {
|
||||||
ZSTD_entropyCTablesMetadata_t entropyMetadata;
|
ZSTD_entropyCTablesMetadata_t entropyMetadata;
|
||||||
|
|
||||||
FORWARD_IF_ERROR(ZSTD_buildSuperBlockEntropy(&zc->seqStore,
|
FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore,
|
||||||
&zc->blockState.prevCBlock->entropy,
|
&zc->blockState.prevCBlock->entropy,
|
||||||
&zc->blockState.nextCBlock->entropy,
|
&zc->blockState.nextCBlock->entropy,
|
||||||
&zc->appliedParams,
|
&zc->appliedParams,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -35,6 +35,10 @@ extern "C" {
|
||||||
#define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128
|
#define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Set our tables and aligneds to align by 64 bytes */
|
||||||
|
#define ZSTD_CWKSP_ALIGNMENT_BYTES 64
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
* Structures
|
* Structures
|
||||||
***************************************/
|
***************************************/
|
||||||
|
@ -117,10 +121,11 @@ typedef enum {
|
||||||
* - Tables: these are any of several different datastructures (hash tables,
|
* - Tables: these are any of several different datastructures (hash tables,
|
||||||
* chain tables, binary trees) that all respect a common format: they are
|
* chain tables, binary trees) that all respect a common format: they are
|
||||||
* uint32_t arrays, all of whose values are between 0 and (nextSrc - base).
|
* uint32_t arrays, all of whose values are between 0 and (nextSrc - base).
|
||||||
* Their sizes depend on the cparams.
|
* Their sizes depend on the cparams. These tables are 64-byte aligned.
|
||||||
*
|
*
|
||||||
* - Aligned: these buffers are used for various purposes that require 4 byte
|
* - Aligned: these buffers are used for various purposes that require 4 byte
|
||||||
* alignment, but don't require any initialization before they're used.
|
* alignment, but don't require any initialization before they're used. These
|
||||||
|
* buffers are each aligned to 64 bytes.
|
||||||
*
|
*
|
||||||
* - Buffers: these buffers are used for various purposes that don't require
|
* - Buffers: these buffers are used for various purposes that don't require
|
||||||
* any alignment or initialization before they're used. This means they can
|
* any alignment or initialization before they're used. This means they can
|
||||||
|
@ -133,8 +138,7 @@ typedef enum {
|
||||||
*
|
*
|
||||||
* 1. Objects
|
* 1. Objects
|
||||||
* 2. Buffers
|
* 2. Buffers
|
||||||
* 3. Aligned
|
* 3. Aligned/Tables
|
||||||
* 4. Tables
|
|
||||||
*
|
*
|
||||||
* Attempts to reserve objects of different types out of order will fail.
|
* Attempts to reserve objects of different types out of order will fail.
|
||||||
*/
|
*/
|
||||||
|
@ -187,6 +191,8 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) {
|
||||||
* Since tables aren't currently redzoned, you don't need to call through this
|
* Since tables aren't currently redzoned, you don't need to call through this
|
||||||
* to figure out how much space you need for the matchState tables. Everything
|
* to figure out how much space you need for the matchState tables. Everything
|
||||||
* else is though.
|
* else is though.
|
||||||
|
*
|
||||||
|
* Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned_alloc_size().
|
||||||
*/
|
*/
|
||||||
MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
|
MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
|
@ -198,30 +204,110 @@ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_STATIC void ZSTD_cwksp_internal_advance_phase(
|
/**
|
||||||
|
* Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes.
|
||||||
|
* Used to determine the number of bytes required for a given "aligned".
|
||||||
|
*/
|
||||||
|
MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) {
|
||||||
|
return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, ZSTD_CWKSP_ALIGNMENT_BYTES));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of additional space the cwksp must allocate
|
||||||
|
* for internal purposes (currently only alignment).
|
||||||
|
*/
|
||||||
|
MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {
|
||||||
|
/* For alignment, the wksp will always allocate an additional n_1=[1, 64] bytes
|
||||||
|
* to align the beginning of tables section, as well as another n_2=[0, 63] bytes
|
||||||
|
* to align the beginning of the aligned secion.
|
||||||
|
*
|
||||||
|
* n_1 + n_2 == 64 bytes if the cwksp is freshly allocated, due to tables and
|
||||||
|
* aligneds being sized in multiples of 64 bytes.
|
||||||
|
*/
|
||||||
|
size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES;
|
||||||
|
return slackSpace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of additional bytes required to align a pointer to the given number of bytes.
|
||||||
|
* alignBytes must be a power of two.
|
||||||
|
*/
|
||||||
|
MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) {
|
||||||
|
size_t const alignBytesMask = alignBytes - 1;
|
||||||
|
size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask;
|
||||||
|
assert((alignBytes & alignBytesMask) == 0);
|
||||||
|
assert(bytes != ZSTD_CWKSP_ALIGNMENT_BYTES);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal function. Do not use directly.
|
||||||
|
* Reserves the given number of bytes within the aligned/buffer segment of the wksp, which
|
||||||
|
* counts from the end of the wksp. (as opposed to the object/table segment)
|
||||||
|
*
|
||||||
|
* Returns a pointer to the beginning of that space.
|
||||||
|
*/
|
||||||
|
MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes) {
|
||||||
|
void* const alloc = (BYTE*)ws->allocStart - bytes;
|
||||||
|
void* const bottom = ws->tableEnd;
|
||||||
|
DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
|
||||||
|
alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
|
||||||
|
ZSTD_cwksp_assert_internal_consistency(ws);
|
||||||
|
assert(alloc >= bottom);
|
||||||
|
if (alloc < bottom) {
|
||||||
|
DEBUGLOG(4, "cwksp: alloc failed!");
|
||||||
|
ws->allocFailed = 1;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (alloc < ws->tableValidEnd) {
|
||||||
|
ws->tableValidEnd = alloc;
|
||||||
|
}
|
||||||
|
ws->allocStart = alloc;
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the cwksp to the next phase, and does any necessary allocations.
|
||||||
|
* Returns a 0 on success, or zstd error
|
||||||
|
*/
|
||||||
|
MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
|
||||||
ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) {
|
ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) {
|
||||||
assert(phase >= ws->phase);
|
assert(phase >= ws->phase);
|
||||||
if (phase > ws->phase) {
|
if (phase > ws->phase) {
|
||||||
|
/* Going from allocating objects to allocating buffers */
|
||||||
if (ws->phase < ZSTD_cwksp_alloc_buffers &&
|
if (ws->phase < ZSTD_cwksp_alloc_buffers &&
|
||||||
phase >= ZSTD_cwksp_alloc_buffers) {
|
phase >= ZSTD_cwksp_alloc_buffers) {
|
||||||
ws->tableValidEnd = ws->objectEnd;
|
ws->tableValidEnd = ws->objectEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Going from allocating buffers to allocating aligneds/tables */
|
||||||
if (ws->phase < ZSTD_cwksp_alloc_aligned &&
|
if (ws->phase < ZSTD_cwksp_alloc_aligned &&
|
||||||
phase >= ZSTD_cwksp_alloc_aligned) {
|
phase >= ZSTD_cwksp_alloc_aligned) {
|
||||||
/* If unaligned allocations down from a too-large top have left us
|
{ /* Align the start of the "aligned" to 64 bytes. Use [1, 64] bytes. */
|
||||||
* unaligned, we need to realign our alloc ptr. Technically, this
|
size_t const bytesToAlign =
|
||||||
* can consume space that is unaccounted for in the neededSpace
|
ZSTD_CWKSP_ALIGNMENT_BYTES - ZSTD_cwksp_bytes_to_align_ptr(ws->allocStart, ZSTD_CWKSP_ALIGNMENT_BYTES);
|
||||||
* calculation. However, I believe this can only happen when the
|
DEBUGLOG(5, "reserving aligned alignment addtl space: %zu", bytesToAlign);
|
||||||
* workspace is too large, and specifically when it is too large
|
ZSTD_STATIC_ASSERT((ZSTD_CWKSP_ALIGNMENT_BYTES & (ZSTD_CWKSP_ALIGNMENT_BYTES - 1)) == 0); /* power of 2 */
|
||||||
* by a larger margin than the space that will be consumed. */
|
RETURN_ERROR_IF(!ZSTD_cwksp_reserve_internal_buffer_space(ws, bytesToAlign),
|
||||||
/* TODO: cleaner, compiler warning friendly way to do this??? */
|
memory_allocation, "aligned phase - alignment initial allocation failed!");
|
||||||
ws->allocStart = (BYTE*)ws->allocStart - ((size_t)ws->allocStart & (sizeof(U32)-1));
|
}
|
||||||
if (ws->allocStart < ws->tableValidEnd) {
|
{ /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */
|
||||||
ws->tableValidEnd = ws->allocStart;
|
void* const alloc = ws->objectEnd;
|
||||||
|
size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES);
|
||||||
|
void* const end = (BYTE*)alloc + bytesToAlign;
|
||||||
|
DEBUGLOG(5, "reserving table alignment addtl space: %zu", bytesToAlign);
|
||||||
|
RETURN_ERROR_IF(end > ws->workspaceEnd, memory_allocation,
|
||||||
|
"table phase - alignment initial allocation failed!");
|
||||||
|
ws->objectEnd = end;
|
||||||
|
ws->tableEnd = end;
|
||||||
|
ws->tableValidEnd = end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ws->phase = phase;
|
ws->phase = phase;
|
||||||
|
ZSTD_cwksp_assert_internal_consistency(ws);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -237,38 +323,25 @@ MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) {
|
||||||
MEM_STATIC void* ZSTD_cwksp_reserve_internal(
|
MEM_STATIC void* ZSTD_cwksp_reserve_internal(
|
||||||
ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) {
|
ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) {
|
||||||
void* alloc;
|
void* alloc;
|
||||||
void* bottom = ws->tableEnd;
|
if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) {
|
||||||
ZSTD_cwksp_internal_advance_phase(ws, phase);
|
|
||||||
alloc = (BYTE *)ws->allocStart - bytes;
|
|
||||||
|
|
||||||
if (bytes == 0)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
||||||
/* over-reserve space */
|
/* over-reserve space */
|
||||||
alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
bytes += 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
|
alloc = ZSTD_cwksp_reserve_internal_buffer_space(ws, bytes);
|
||||||
alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
|
|
||||||
ZSTD_cwksp_assert_internal_consistency(ws);
|
|
||||||
assert(alloc >= bottom);
|
|
||||||
if (alloc < bottom) {
|
|
||||||
DEBUGLOG(4, "cwksp: alloc failed!");
|
|
||||||
ws->allocFailed = 1;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (alloc < ws->tableValidEnd) {
|
|
||||||
ws->tableValidEnd = alloc;
|
|
||||||
}
|
|
||||||
ws->allocStart = alloc;
|
|
||||||
|
|
||||||
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
||||||
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
|
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
|
||||||
* either size. */
|
* either size. */
|
||||||
alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
if (alloc) {
|
||||||
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
||||||
__asan_unpoison_memory_region(alloc, bytes);
|
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
||||||
|
__asan_unpoison_memory_region(alloc, bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -283,28 +356,36 @@ MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserves and returns memory sized on and aligned on sizeof(unsigned).
|
* Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).
|
||||||
*/
|
*/
|
||||||
MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
|
MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
|
||||||
assert((bytes & (sizeof(U32)-1)) == 0);
|
void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),
|
||||||
return ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, sizeof(U32)), ZSTD_cwksp_alloc_aligned);
|
ZSTD_cwksp_alloc_aligned);
|
||||||
|
assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aligned on sizeof(unsigned). These buffers have the special property that
|
* Aligned on 64 bytes. These buffers have the special property that
|
||||||
* their values remain constrained, allowing us to re-use them without
|
* their values remain constrained, allowing us to re-use them without
|
||||||
* memset()-ing them.
|
* memset()-ing them.
|
||||||
*/
|
*/
|
||||||
MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
|
MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
|
||||||
const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned;
|
const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned;
|
||||||
void* alloc = ws->tableEnd;
|
void* alloc;
|
||||||
void* end = (BYTE *)alloc + bytes;
|
void* end;
|
||||||
void* top = ws->allocStart;
|
void* top;
|
||||||
|
|
||||||
|
if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
alloc = ws->tableEnd;
|
||||||
|
end = (BYTE *)alloc + bytes;
|
||||||
|
top = ws->allocStart;
|
||||||
|
|
||||||
DEBUGLOG(5, "cwksp: reserving %p table %zd bytes, %zd bytes remaining",
|
DEBUGLOG(5, "cwksp: reserving %p table %zd bytes, %zd bytes remaining",
|
||||||
alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
|
alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);
|
||||||
assert((bytes & (sizeof(U32)-1)) == 0);
|
assert((bytes & (sizeof(U32)-1)) == 0);
|
||||||
ZSTD_cwksp_internal_advance_phase(ws, phase);
|
|
||||||
ZSTD_cwksp_assert_internal_consistency(ws);
|
ZSTD_cwksp_assert_internal_consistency(ws);
|
||||||
assert(end <= top);
|
assert(end <= top);
|
||||||
if (end > top) {
|
if (end > top) {
|
||||||
|
@ -320,6 +401,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);
|
||||||
|
assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
|
||||||
return alloc;
|
return alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +586,7 @@ MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the management of a workspace from one cwksp to another. The src cwksp
|
* Moves the management of a workspace from one cwksp to another. The src cwksp
|
||||||
* is left in an invalid state (src must be re-init()'ed before its used again).
|
* is left in an invalid state (src must be re-init()'ed before it's used again).
|
||||||
*/
|
*/
|
||||||
MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {
|
MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
|
@ -527,6 +610,24 @@ MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {
|
||||||
* Functions Checking Free Space
|
* Functions Checking Free Space
|
||||||
***************************************/
|
***************************************/
|
||||||
|
|
||||||
|
/* ZSTD_alignmentSpaceWithinBounds() :
|
||||||
|
* Returns if the estimated space needed for a wksp is within an acceptable limit of the
|
||||||
|
* actual amount of space used.
|
||||||
|
*/
|
||||||
|
MEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp* const ws,
|
||||||
|
size_t const estimatedSpace, int resizedWorkspace) {
|
||||||
|
if (resizedWorkspace) {
|
||||||
|
/* Resized/newly allocated wksp should have exact bounds */
|
||||||
|
return ZSTD_cwksp_used(ws) == estimatedSpace;
|
||||||
|
} else {
|
||||||
|
/* Due to alignment, when reusing a workspace, we can actually consume 63 fewer or more bytes
|
||||||
|
* than estimatedSpace. See the comments in zstd_cwksp.h for details.
|
||||||
|
*/
|
||||||
|
return (ZSTD_cwksp_used(ws) >= estimatedSpace - 63) && (ZSTD_cwksp_used(ws) <= estimatedSpace + 63);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) {
|
MEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) {
|
||||||
return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd);
|
return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -409,7 +409,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||||
hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */
|
hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */
|
||||||
|
|
||||||
if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
|
if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
|
||||||
& (repIndex > dictStartIndex))
|
& (offset_1 < curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */
|
||||||
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
||||||
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||||
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
|
||||||
|
@ -477,7 +477,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
|
||||||
U32 const repIndex2 = current2 - offset_2;
|
U32 const repIndex2 = current2 - offset_2;
|
||||||
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
|
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
|
||||||
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
|
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
|
||||||
& (repIndex2 > dictStartIndex))
|
& (offset_2 < current2 - dictStartIndex))
|
||||||
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
||||||
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
||||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -242,7 +242,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
|
||||||
assert(endIndex - prefixStartIndex <= maxDistance);
|
assert(endIndex - prefixStartIndex <= maxDistance);
|
||||||
(void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */
|
(void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */
|
||||||
|
|
||||||
/* ensure there will be no no underflow
|
/* ensure there will be no underflow
|
||||||
* when translating a dict index into a local index */
|
* when translating a dict index into a local index */
|
||||||
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
|
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
|
||||||
|
|
||||||
|
@ -416,9 +416,9 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||||
const BYTE* const repMatch = repBase + repIndex;
|
const BYTE* const repMatch = repBase + repIndex;
|
||||||
hashTable[h] = curr; /* update hash table */
|
hashTable[h] = curr; /* update hash table */
|
||||||
DEBUGLOG(7, "offset_1 = %u , curr = %u", offset_1, curr);
|
DEBUGLOG(7, "offset_1 = %u , curr = %u", offset_1, curr);
|
||||||
assert(offset_1 <= curr +1); /* check repIndex */
|
|
||||||
|
|
||||||
if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex))
|
if ( ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */
|
||||||
|
& (offset_1 < curr+1 - dictStartIndex) ) /* note: we are searching at curr+1 */
|
||||||
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
|
||||||
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
|
||||||
size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4;
|
size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4;
|
||||||
|
@ -453,7 +453,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
|
||||||
U32 const current2 = (U32)(ip-base);
|
U32 const current2 = (U32)(ip-base);
|
||||||
U32 const repIndex2 = current2 - offset_2;
|
U32 const repIndex2 = current2 - offset_2;
|
||||||
const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
|
const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
|
||||||
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (repIndex2 > dictStartIndex)) /* intentional overflow */
|
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 < curr - dictStartIndex)) /* intentional overflow */
|
||||||
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
|
||||||
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
|
||||||
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -26,6 +26,7 @@ extern "C" {
|
||||||
#define ZSTD_LAZY_DDSS_BUCKET_LOG 2
|
#define ZSTD_LAZY_DDSS_BUCKET_LOG 2
|
||||||
|
|
||||||
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
|
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
|
||||||
|
void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip);
|
||||||
|
|
||||||
void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip);
|
void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip);
|
||||||
|
|
||||||
|
@ -43,6 +44,15 @@ size_t ZSTD_compressBlock_lazy(
|
||||||
size_t ZSTD_compressBlock_greedy(
|
size_t ZSTD_compressBlock_greedy(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize);
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy2_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_greedy_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
|
||||||
size_t ZSTD_compressBlock_btlazy2_dictMatchState(
|
size_t ZSTD_compressBlock_btlazy2_dictMatchState(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
@ -56,6 +66,15 @@ size_t ZSTD_compressBlock_lazy_dictMatchState(
|
||||||
size_t ZSTD_compressBlock_greedy_dictMatchState(
|
size_t ZSTD_compressBlock_greedy_dictMatchState(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize);
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy2_dictMatchState_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy_dictMatchState_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_greedy_dictMatchState_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
|
||||||
size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(
|
size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
@ -66,6 +85,15 @@ size_t ZSTD_compressBlock_lazy_dedicatedDictSearch(
|
||||||
size_t ZSTD_compressBlock_greedy_dedicatedDictSearch(
|
size_t ZSTD_compressBlock_greedy_dedicatedDictSearch(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize);
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
|
||||||
size_t ZSTD_compressBlock_greedy_extDict(
|
size_t ZSTD_compressBlock_greedy_extDict(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
@ -76,9 +104,19 @@ size_t ZSTD_compressBlock_lazy_extDict(
|
||||||
size_t ZSTD_compressBlock_lazy2_extDict(
|
size_t ZSTD_compressBlock_lazy2_extDict(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize);
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_greedy_extDict_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy_extDict_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
|
size_t ZSTD_compressBlock_lazy2_extDict_row(
|
||||||
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
void const* src, size_t srcSize);
|
||||||
size_t ZSTD_compressBlock_btlazy2_extDict(
|
size_t ZSTD_compressBlock_btlazy2_extDict(
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
void const* src, size_t srcSize);
|
void const* src, size_t srcSize);
|
||||||
|
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -11,13 +11,126 @@
|
||||||
#include "zstd_ldm.h"
|
#include "zstd_ldm.h"
|
||||||
|
|
||||||
#include "../common/debug.h"
|
#include "../common/debug.h"
|
||||||
|
#include "../common/xxhash.h"
|
||||||
#include "zstd_fast.h" /* ZSTD_fillHashTable() */
|
#include "zstd_fast.h" /* ZSTD_fillHashTable() */
|
||||||
#include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */
|
#include "zstd_double_fast.h" /* ZSTD_fillDoubleHashTable() */
|
||||||
|
#include "zstd_ldm_geartab.h"
|
||||||
|
|
||||||
#define LDM_BUCKET_SIZE_LOG 3
|
#define LDM_BUCKET_SIZE_LOG 3
|
||||||
#define LDM_MIN_MATCH_LENGTH 64
|
#define LDM_MIN_MATCH_LENGTH 64
|
||||||
#define LDM_HASH_RLOG 7
|
#define LDM_HASH_RLOG 7
|
||||||
#define LDM_HASH_CHAR_OFFSET 10
|
|
||||||
|
typedef struct {
|
||||||
|
U64 rolling;
|
||||||
|
U64 stopMask;
|
||||||
|
} ldmRollingHashState_t;
|
||||||
|
|
||||||
|
/** ZSTD_ldm_gear_init():
|
||||||
|
*
|
||||||
|
* Initializes the rolling hash state such that it will honor the
|
||||||
|
* settings in params. */
|
||||||
|
static void ZSTD_ldm_gear_init(ldmRollingHashState_t* state, ldmParams_t const* params)
|
||||||
|
{
|
||||||
|
unsigned maxBitsInMask = MIN(params->minMatchLength, 64);
|
||||||
|
unsigned hashRateLog = params->hashRateLog;
|
||||||
|
|
||||||
|
state->rolling = ~(U32)0;
|
||||||
|
|
||||||
|
/* The choice of the splitting criterion is subject to two conditions:
|
||||||
|
* 1. it has to trigger on average every 2^(hashRateLog) bytes;
|
||||||
|
* 2. ideally, it has to depend on a window of minMatchLength bytes.
|
||||||
|
*
|
||||||
|
* In the gear hash algorithm, bit n depends on the last n bytes;
|
||||||
|
* so in order to obtain a good quality splitting criterion it is
|
||||||
|
* preferable to use bits with high weight.
|
||||||
|
*
|
||||||
|
* To match condition 1 we use a mask with hashRateLog bits set
|
||||||
|
* and, because of the previous remark, we make sure these bits
|
||||||
|
* have the highest possible weight while still respecting
|
||||||
|
* condition 2.
|
||||||
|
*/
|
||||||
|
if (hashRateLog > 0 && hashRateLog <= maxBitsInMask) {
|
||||||
|
state->stopMask = (((U64)1 << hashRateLog) - 1) << (maxBitsInMask - hashRateLog);
|
||||||
|
} else {
|
||||||
|
/* In this degenerate case we simply honor the hash rate. */
|
||||||
|
state->stopMask = ((U64)1 << hashRateLog) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ZSTD_ldm_gear_reset()
|
||||||
|
* Feeds [data, data + minMatchLength) into the hash without registering any
|
||||||
|
* splits. This effectively resets the hash state. This is used when skipping
|
||||||
|
* over data, either at the beginning of a block, or skipping sections.
|
||||||
|
*/
|
||||||
|
static void ZSTD_ldm_gear_reset(ldmRollingHashState_t* state,
|
||||||
|
BYTE const* data, size_t minMatchLength)
|
||||||
|
{
|
||||||
|
U64 hash = state->rolling;
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
#define GEAR_ITER_ONCE() do { \
|
||||||
|
hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \
|
||||||
|
n += 1; \
|
||||||
|
} while (0)
|
||||||
|
while (n + 3 < minMatchLength) {
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
}
|
||||||
|
while (n < minMatchLength) {
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
}
|
||||||
|
#undef GEAR_ITER_ONCE
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ZSTD_ldm_gear_feed():
|
||||||
|
*
|
||||||
|
* Registers in the splits array all the split points found in the first
|
||||||
|
* size bytes following the data pointer. This function terminates when
|
||||||
|
* either all the data has been processed or LDM_BATCH_SIZE splits are
|
||||||
|
* present in the splits array.
|
||||||
|
*
|
||||||
|
* Precondition: The splits array must not be full.
|
||||||
|
* Returns: The number of bytes processed. */
|
||||||
|
static size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state,
|
||||||
|
BYTE const* data, size_t size,
|
||||||
|
size_t* splits, unsigned* numSplits)
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
U64 hash, mask;
|
||||||
|
|
||||||
|
hash = state->rolling;
|
||||||
|
mask = state->stopMask;
|
||||||
|
n = 0;
|
||||||
|
|
||||||
|
#define GEAR_ITER_ONCE() do { \
|
||||||
|
hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \
|
||||||
|
n += 1; \
|
||||||
|
if (UNLIKELY((hash & mask) == 0)) { \
|
||||||
|
splits[*numSplits] = n; \
|
||||||
|
*numSplits += 1; \
|
||||||
|
if (*numSplits == LDM_BATCH_SIZE) \
|
||||||
|
goto done; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
while (n + 3 < size) {
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
}
|
||||||
|
while (n < size) {
|
||||||
|
GEAR_ITER_ONCE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef GEAR_ITER_ONCE
|
||||||
|
|
||||||
|
done:
|
||||||
|
state->rolling = hash;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
void ZSTD_ldm_adjustParameters(ldmParams_t* params,
|
void ZSTD_ldm_adjustParameters(ldmParams_t* params,
|
||||||
ZSTD_compressionParameters const* cParams)
|
ZSTD_compressionParameters const* cParams)
|
||||||
|
@ -54,41 +167,6 @@ size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)
|
||||||
return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0;
|
return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ZSTD_ldm_getSmallHash() :
|
|
||||||
* numBits should be <= 32
|
|
||||||
* If numBits==0, returns 0.
|
|
||||||
* @return : the most significant numBits of value. */
|
|
||||||
static U32 ZSTD_ldm_getSmallHash(U64 value, U32 numBits)
|
|
||||||
{
|
|
||||||
assert(numBits <= 32);
|
|
||||||
return numBits == 0 ? 0 : (U32)(value >> (64 - numBits));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ZSTD_ldm_getChecksum() :
|
|
||||||
* numBitsToDiscard should be <= 32
|
|
||||||
* @return : the next most significant 32 bits after numBitsToDiscard */
|
|
||||||
static U32 ZSTD_ldm_getChecksum(U64 hash, U32 numBitsToDiscard)
|
|
||||||
{
|
|
||||||
assert(numBitsToDiscard <= 32);
|
|
||||||
return (hash >> (64 - 32 - numBitsToDiscard)) & 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ZSTD_ldm_getTag() ;
|
|
||||||
* Given the hash, returns the most significant numTagBits bits
|
|
||||||
* after (32 + hbits) bits.
|
|
||||||
*
|
|
||||||
* If there are not enough bits remaining, return the last
|
|
||||||
* numTagBits bits. */
|
|
||||||
static U32 ZSTD_ldm_getTag(U64 hash, U32 hbits, U32 numTagBits)
|
|
||||||
{
|
|
||||||
assert(numTagBits < 32 && hbits <= 32);
|
|
||||||
if (32 - hbits < numTagBits) {
|
|
||||||
return hash & (((U32)1 << numTagBits) - 1);
|
|
||||||
} else {
|
|
||||||
return (hash >> (32 - hbits - numTagBits)) & (((U32)1 << numTagBits) - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** ZSTD_ldm_getBucket() :
|
/** ZSTD_ldm_getBucket() :
|
||||||
* Returns a pointer to the start of the bucket associated with hash. */
|
* Returns a pointer to the start of the bucket associated with hash. */
|
||||||
static ldmEntry_t* ZSTD_ldm_getBucket(
|
static ldmEntry_t* ZSTD_ldm_getBucket(
|
||||||
|
@ -103,38 +181,12 @@ static void ZSTD_ldm_insertEntry(ldmState_t* ldmState,
|
||||||
size_t const hash, const ldmEntry_t entry,
|
size_t const hash, const ldmEntry_t entry,
|
||||||
ldmParams_t const ldmParams)
|
ldmParams_t const ldmParams)
|
||||||
{
|
{
|
||||||
BYTE* const bucketOffsets = ldmState->bucketOffsets;
|
BYTE* const pOffset = ldmState->bucketOffsets + hash;
|
||||||
*(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + bucketOffsets[hash]) = entry;
|
unsigned const offset = *pOffset;
|
||||||
bucketOffsets[hash]++;
|
|
||||||
bucketOffsets[hash] &= ((U32)1 << ldmParams.bucketSizeLog) - 1;
|
*(ZSTD_ldm_getBucket(ldmState, hash, ldmParams) + offset) = entry;
|
||||||
}
|
*pOffset = (BYTE)((offset + 1) & ((1u << ldmParams.bucketSizeLog) - 1));
|
||||||
|
|
||||||
/** ZSTD_ldm_makeEntryAndInsertByTag() :
|
|
||||||
*
|
|
||||||
* Gets the small hash, checksum, and tag from the rollingHash.
|
|
||||||
*
|
|
||||||
* If the tag matches (1 << ldmParams.hashRateLog)-1, then
|
|
||||||
* creates an ldmEntry from the offset, and inserts it into the hash table.
|
|
||||||
*
|
|
||||||
* hBits is the length of the small hash, which is the most significant hBits
|
|
||||||
* of rollingHash. The checksum is the next 32 most significant bits, followed
|
|
||||||
* by ldmParams.hashRateLog bits that make up the tag. */
|
|
||||||
static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState,
|
|
||||||
U64 const rollingHash,
|
|
||||||
U32 const hBits,
|
|
||||||
U32 const offset,
|
|
||||||
ldmParams_t const ldmParams)
|
|
||||||
{
|
|
||||||
U32 const tag = ZSTD_ldm_getTag(rollingHash, hBits, ldmParams.hashRateLog);
|
|
||||||
U32 const tagMask = ((U32)1 << ldmParams.hashRateLog) - 1;
|
|
||||||
if (tag == tagMask) {
|
|
||||||
U32 const hash = ZSTD_ldm_getSmallHash(rollingHash, hBits);
|
|
||||||
U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
|
|
||||||
ldmEntry_t entry;
|
|
||||||
entry.offset = offset;
|
|
||||||
entry.checksum = checksum;
|
|
||||||
ZSTD_ldm_insertEntry(ldmState, hash, entry, ldmParams);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ZSTD_ldm_countBackwardsMatch() :
|
/** ZSTD_ldm_countBackwardsMatch() :
|
||||||
|
@ -212,43 +264,42 @@ static size_t ZSTD_ldm_fillFastTables(ZSTD_matchState_t* ms,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ZSTD_ldm_fillLdmHashTable() :
|
|
||||||
*
|
|
||||||
* Fills hashTable from (lastHashed + 1) to iend (non-inclusive).
|
|
||||||
* lastHash is the rolling hash that corresponds to lastHashed.
|
|
||||||
*
|
|
||||||
* Returns the rolling hash corresponding to position iend-1. */
|
|
||||||
static U64 ZSTD_ldm_fillLdmHashTable(ldmState_t* state,
|
|
||||||
U64 lastHash, const BYTE* lastHashed,
|
|
||||||
const BYTE* iend, const BYTE* base,
|
|
||||||
U32 hBits, ldmParams_t const ldmParams)
|
|
||||||
{
|
|
||||||
U64 rollingHash = lastHash;
|
|
||||||
const BYTE* cur = lastHashed + 1;
|
|
||||||
|
|
||||||
while (cur < iend) {
|
|
||||||
rollingHash = ZSTD_rollingHash_rotate(rollingHash, cur[-1],
|
|
||||||
cur[ldmParams.minMatchLength-1],
|
|
||||||
state->hashPower);
|
|
||||||
ZSTD_ldm_makeEntryAndInsertByTag(state,
|
|
||||||
rollingHash, hBits,
|
|
||||||
(U32)(cur - base), ldmParams);
|
|
||||||
++cur;
|
|
||||||
}
|
|
||||||
return rollingHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZSTD_ldm_fillHashTable(
|
void ZSTD_ldm_fillHashTable(
|
||||||
ldmState_t* state, const BYTE* ip,
|
ldmState_t* ldmState, const BYTE* ip,
|
||||||
const BYTE* iend, ldmParams_t const* params)
|
const BYTE* iend, ldmParams_t const* params)
|
||||||
{
|
{
|
||||||
|
U32 const minMatchLength = params->minMatchLength;
|
||||||
|
U32 const hBits = params->hashLog - params->bucketSizeLog;
|
||||||
|
BYTE const* const base = ldmState->window.base;
|
||||||
|
BYTE const* const istart = ip;
|
||||||
|
ldmRollingHashState_t hashState;
|
||||||
|
size_t* const splits = ldmState->splitIndices;
|
||||||
|
unsigned numSplits;
|
||||||
|
|
||||||
DEBUGLOG(5, "ZSTD_ldm_fillHashTable");
|
DEBUGLOG(5, "ZSTD_ldm_fillHashTable");
|
||||||
if ((size_t)(iend - ip) >= params->minMatchLength) {
|
|
||||||
U64 startingHash = ZSTD_rollingHash_compute(ip, params->minMatchLength);
|
ZSTD_ldm_gear_init(&hashState, params);
|
||||||
ZSTD_ldm_fillLdmHashTable(
|
while (ip < iend) {
|
||||||
state, startingHash, ip, iend - params->minMatchLength, state->window.base,
|
size_t hashed;
|
||||||
params->hashLog - params->bucketSizeLog,
|
unsigned n;
|
||||||
*params);
|
|
||||||
|
numSplits = 0;
|
||||||
|
hashed = ZSTD_ldm_gear_feed(&hashState, ip, iend - ip, splits, &numSplits);
|
||||||
|
|
||||||
|
for (n = 0; n < numSplits; n++) {
|
||||||
|
if (ip + splits[n] >= istart + minMatchLength) {
|
||||||
|
BYTE const* const split = ip + splits[n] - minMatchLength;
|
||||||
|
U64 const xxhash = XXH64(split, minMatchLength, 0);
|
||||||
|
U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));
|
||||||
|
ldmEntry_t entry;
|
||||||
|
|
||||||
|
entry.offset = (U32)(split - base);
|
||||||
|
entry.checksum = (U32)(xxhash >> 32);
|
||||||
|
ZSTD_ldm_insertEntry(ldmState, hash, entry, *params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ip += hashed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,11 +325,8 @@ static size_t ZSTD_ldm_generateSequences_internal(
|
||||||
/* LDM parameters */
|
/* LDM parameters */
|
||||||
int const extDict = ZSTD_window_hasExtDict(ldmState->window);
|
int const extDict = ZSTD_window_hasExtDict(ldmState->window);
|
||||||
U32 const minMatchLength = params->minMatchLength;
|
U32 const minMatchLength = params->minMatchLength;
|
||||||
U64 const hashPower = ldmState->hashPower;
|
U32 const entsPerBucket = 1U << params->bucketSizeLog;
|
||||||
U32 const hBits = params->hashLog - params->bucketSizeLog;
|
U32 const hBits = params->hashLog - params->bucketSizeLog;
|
||||||
U32 const ldmBucketSize = 1U << params->bucketSizeLog;
|
|
||||||
U32 const hashRateLog = params->hashRateLog;
|
|
||||||
U32 const ldmTagMask = (1U << params->hashRateLog) - 1;
|
|
||||||
/* Prefix and extDict parameters */
|
/* Prefix and extDict parameters */
|
||||||
U32 const dictLimit = ldmState->window.dictLimit;
|
U32 const dictLimit = ldmState->window.dictLimit;
|
||||||
U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;
|
U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;
|
||||||
|
@ -290,45 +338,69 @@ static size_t ZSTD_ldm_generateSequences_internal(
|
||||||
/* Input bounds */
|
/* Input bounds */
|
||||||
BYTE const* const istart = (BYTE const*)src;
|
BYTE const* const istart = (BYTE const*)src;
|
||||||
BYTE const* const iend = istart + srcSize;
|
BYTE const* const iend = istart + srcSize;
|
||||||
BYTE const* const ilimit = iend - MAX(minMatchLength, HASH_READ_SIZE);
|
BYTE const* const ilimit = iend - HASH_READ_SIZE;
|
||||||
/* Input positions */
|
/* Input positions */
|
||||||
BYTE const* anchor = istart;
|
BYTE const* anchor = istart;
|
||||||
BYTE const* ip = istart;
|
BYTE const* ip = istart;
|
||||||
/* Rolling hash */
|
/* Rolling hash state */
|
||||||
BYTE const* lastHashed = NULL;
|
ldmRollingHashState_t hashState;
|
||||||
U64 rollingHash = 0;
|
/* Arrays for staged-processing */
|
||||||
|
size_t* const splits = ldmState->splitIndices;
|
||||||
|
ldmMatchCandidate_t* const candidates = ldmState->matchCandidates;
|
||||||
|
unsigned numSplits;
|
||||||
|
|
||||||
while (ip <= ilimit) {
|
if (srcSize < minMatchLength)
|
||||||
size_t mLength;
|
return iend - anchor;
|
||||||
U32 const curr = (U32)(ip - base);
|
|
||||||
size_t forwardMatchLength = 0, backwardMatchLength = 0;
|
|
||||||
ldmEntry_t* bestEntry = NULL;
|
|
||||||
if (ip != istart) {
|
|
||||||
rollingHash = ZSTD_rollingHash_rotate(rollingHash, lastHashed[0],
|
|
||||||
lastHashed[minMatchLength],
|
|
||||||
hashPower);
|
|
||||||
} else {
|
|
||||||
rollingHash = ZSTD_rollingHash_compute(ip, minMatchLength);
|
|
||||||
}
|
|
||||||
lastHashed = ip;
|
|
||||||
|
|
||||||
/* Do not insert and do not look for a match */
|
/* Initialize the rolling hash state with the first minMatchLength bytes */
|
||||||
if (ZSTD_ldm_getTag(rollingHash, hBits, hashRateLog) != ldmTagMask) {
|
ZSTD_ldm_gear_init(&hashState, params);
|
||||||
ip++;
|
ZSTD_ldm_gear_reset(&hashState, ip, minMatchLength);
|
||||||
continue;
|
ip += minMatchLength;
|
||||||
|
|
||||||
|
while (ip < ilimit) {
|
||||||
|
size_t hashed;
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
|
numSplits = 0;
|
||||||
|
hashed = ZSTD_ldm_gear_feed(&hashState, ip, ilimit - ip,
|
||||||
|
splits, &numSplits);
|
||||||
|
|
||||||
|
for (n = 0; n < numSplits; n++) {
|
||||||
|
BYTE const* const split = ip + splits[n] - minMatchLength;
|
||||||
|
U64 const xxhash = XXH64(split, minMatchLength, 0);
|
||||||
|
U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));
|
||||||
|
|
||||||
|
candidates[n].split = split;
|
||||||
|
candidates[n].hash = hash;
|
||||||
|
candidates[n].checksum = (U32)(xxhash >> 32);
|
||||||
|
candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, *params);
|
||||||
|
PREFETCH_L1(candidates[n].bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the best entry and compute the match lengths */
|
for (n = 0; n < numSplits; n++) {
|
||||||
{
|
size_t forwardMatchLength = 0, backwardMatchLength = 0,
|
||||||
ldmEntry_t* const bucket =
|
bestMatchLength = 0, mLength;
|
||||||
ZSTD_ldm_getBucket(ldmState,
|
U32 offset;
|
||||||
ZSTD_ldm_getSmallHash(rollingHash, hBits),
|
BYTE const* const split = candidates[n].split;
|
||||||
*params);
|
U32 const checksum = candidates[n].checksum;
|
||||||
ldmEntry_t* cur;
|
U32 const hash = candidates[n].hash;
|
||||||
size_t bestMatchLength = 0;
|
ldmEntry_t* const bucket = candidates[n].bucket;
|
||||||
U32 const checksum = ZSTD_ldm_getChecksum(rollingHash, hBits);
|
ldmEntry_t const* cur;
|
||||||
|
ldmEntry_t const* bestEntry = NULL;
|
||||||
|
ldmEntry_t newEntry;
|
||||||
|
|
||||||
for (cur = bucket; cur < bucket + ldmBucketSize; ++cur) {
|
newEntry.offset = (U32)(split - base);
|
||||||
|
newEntry.checksum = checksum;
|
||||||
|
|
||||||
|
/* If a split point would generate a sequence overlapping with
|
||||||
|
* the previous one, we merely register it in the hash table and
|
||||||
|
* move on */
|
||||||
|
if (split < anchor) {
|
||||||
|
ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cur = bucket; cur < bucket + entsPerBucket; cur++) {
|
||||||
size_t curForwardMatchLength, curBackwardMatchLength,
|
size_t curForwardMatchLength, curBackwardMatchLength,
|
||||||
curTotalMatchLength;
|
curTotalMatchLength;
|
||||||
if (cur->checksum != checksum || cur->offset <= lowestIndex) {
|
if (cur->checksum != checksum || cur->offset <= lowestIndex) {
|
||||||
|
@ -342,31 +414,23 @@ static size_t ZSTD_ldm_generateSequences_internal(
|
||||||
cur->offset < dictLimit ? dictEnd : iend;
|
cur->offset < dictLimit ? dictEnd : iend;
|
||||||
BYTE const* const lowMatchPtr =
|
BYTE const* const lowMatchPtr =
|
||||||
cur->offset < dictLimit ? dictStart : lowPrefixPtr;
|
cur->offset < dictLimit ? dictStart : lowPrefixPtr;
|
||||||
|
curForwardMatchLength =
|
||||||
curForwardMatchLength = ZSTD_count_2segments(
|
ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr);
|
||||||
ip, pMatch, iend,
|
|
||||||
matchEnd, lowPrefixPtr);
|
|
||||||
if (curForwardMatchLength < minMatchLength) {
|
if (curForwardMatchLength < minMatchLength) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
curBackwardMatchLength =
|
curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments(
|
||||||
ZSTD_ldm_countBackwardsMatch_2segments(ip, anchor,
|
split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd);
|
||||||
pMatch, lowMatchPtr,
|
|
||||||
dictStart, dictEnd);
|
|
||||||
curTotalMatchLength = curForwardMatchLength +
|
|
||||||
curBackwardMatchLength;
|
|
||||||
} else { /* !extDict */
|
} else { /* !extDict */
|
||||||
BYTE const* const pMatch = base + cur->offset;
|
BYTE const* const pMatch = base + cur->offset;
|
||||||
curForwardMatchLength = ZSTD_count(ip, pMatch, iend);
|
curForwardMatchLength = ZSTD_count(split, pMatch, iend);
|
||||||
if (curForwardMatchLength < minMatchLength) {
|
if (curForwardMatchLength < minMatchLength) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
curBackwardMatchLength =
|
curBackwardMatchLength =
|
||||||
ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch,
|
ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr);
|
||||||
lowPrefixPtr);
|
|
||||||
curTotalMatchLength = curForwardMatchLength +
|
|
||||||
curBackwardMatchLength;
|
|
||||||
}
|
}
|
||||||
|
curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength;
|
||||||
|
|
||||||
if (curTotalMatchLength > bestMatchLength) {
|
if (curTotalMatchLength > bestMatchLength) {
|
||||||
bestMatchLength = curTotalMatchLength;
|
bestMatchLength = curTotalMatchLength;
|
||||||
|
@ -375,57 +439,54 @@ static size_t ZSTD_ldm_generateSequences_internal(
|
||||||
bestEntry = cur;
|
bestEntry = cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* No match found -- continue searching */
|
/* No match found -- insert an entry into the hash table
|
||||||
if (bestEntry == NULL) {
|
* and process the next candidate match */
|
||||||
ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash,
|
if (bestEntry == NULL) {
|
||||||
hBits, curr,
|
ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
|
||||||
*params);
|
continue;
|
||||||
ip++;
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Match found */
|
/* Match found */
|
||||||
mLength = forwardMatchLength + backwardMatchLength;
|
offset = (U32)(split - base) - bestEntry->offset;
|
||||||
ip -= backwardMatchLength;
|
mLength = forwardMatchLength + backwardMatchLength;
|
||||||
|
{
|
||||||
|
rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;
|
||||||
|
|
||||||
{
|
/* Out of sequence storage */
|
||||||
/* Store the sequence:
|
if (rawSeqStore->size == rawSeqStore->capacity)
|
||||||
* ip = curr - backwardMatchLength
|
return ERROR(dstSize_tooSmall);
|
||||||
* The match is at (bestEntry->offset - backwardMatchLength)
|
seq->litLength = (U32)(split - backwardMatchLength - anchor);
|
||||||
|
seq->matchLength = (U32)mLength;
|
||||||
|
seq->offset = offset;
|
||||||
|
rawSeqStore->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert the current entry into the hash table --- it must be
|
||||||
|
* done after the previous block to avoid clobbering bestEntry */
|
||||||
|
ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *params);
|
||||||
|
|
||||||
|
anchor = split + forwardMatchLength;
|
||||||
|
|
||||||
|
/* If we find a match that ends after the data that we've hashed
|
||||||
|
* then we have a repeating, overlapping, pattern. E.g. all zeros.
|
||||||
|
* If one repetition of the pattern matches our `stopMask` then all
|
||||||
|
* repetitions will. We don't need to insert them all into out table,
|
||||||
|
* only the first one. So skip over overlapping matches.
|
||||||
|
* This is a major speed boost (20x) for compressing a single byte
|
||||||
|
* repeated, when that byte ends up in the table.
|
||||||
*/
|
*/
|
||||||
U32 const matchIndex = bestEntry->offset;
|
if (anchor > ip + hashed) {
|
||||||
U32 const offset = curr - matchIndex;
|
ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength);
|
||||||
rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;
|
/* Continue the outter loop at anchor (ip + hashed == anchor). */
|
||||||
|
ip = anchor - hashed;
|
||||||
/* Out of sequence storage */
|
break;
|
||||||
if (rawSeqStore->size == rawSeqStore->capacity)
|
}
|
||||||
return ERROR(dstSize_tooSmall);
|
|
||||||
seq->litLength = (U32)(ip - anchor);
|
|
||||||
seq->matchLength = (U32)mLength;
|
|
||||||
seq->offset = offset;
|
|
||||||
rawSeqStore->size++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert the current entry into the hash table */
|
ip += hashed;
|
||||||
ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, hBits,
|
|
||||||
(U32)(lastHashed - base),
|
|
||||||
*params);
|
|
||||||
|
|
||||||
assert(ip + backwardMatchLength == lastHashed);
|
|
||||||
|
|
||||||
/* Fill the hash table from lastHashed+1 to ip+mLength*/
|
|
||||||
/* Heuristic: don't need to fill the entire table at end of block */
|
|
||||||
if (ip + mLength <= ilimit) {
|
|
||||||
rollingHash = ZSTD_ldm_fillLdmHashTable(
|
|
||||||
ldmState, rollingHash, lastHashed,
|
|
||||||
ip + mLength, base, hBits, *params);
|
|
||||||
lastHashed = ip + mLength - 1;
|
|
||||||
}
|
|
||||||
ip += mLength;
|
|
||||||
anchor = ip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return iend - anchor;
|
return iend - anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,7 +535,7 @@ size_t ZSTD_ldm_generateSequences(
|
||||||
|
|
||||||
assert(chunkStart < iend);
|
assert(chunkStart < iend);
|
||||||
/* 1. Perform overflow correction if necessary. */
|
/* 1. Perform overflow correction if necessary. */
|
||||||
if (ZSTD_window_needOverflowCorrection(ldmState->window, chunkEnd)) {
|
if (ZSTD_window_needOverflowCorrection(ldmState->window, 0, maxDist, ldmState->loadedDictEnd, chunkStart, chunkEnd)) {
|
||||||
U32 const ldmHSize = 1U << params->hashLog;
|
U32 const ldmHSize = 1U << params->hashLog;
|
||||||
U32 const correction = ZSTD_window_correctOverflow(
|
U32 const correction = ZSTD_window_correctOverflow(
|
||||||
&ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);
|
&ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);
|
||||||
|
@ -596,12 +657,13 @@ void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
|
||||||
|
|
||||||
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
|
||||||
void const* src, size_t srcSize)
|
void const* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||||
unsigned const minMatch = cParams->minMatch;
|
unsigned const minMatch = cParams->minMatch;
|
||||||
ZSTD_blockCompressor const blockCompressor =
|
ZSTD_blockCompressor const blockCompressor =
|
||||||
ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms));
|
ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms));
|
||||||
/* Input bounds */
|
/* Input bounds */
|
||||||
BYTE const* const istart = (BYTE const*)src;
|
BYTE const* const istart = (BYTE const*)src;
|
||||||
BYTE const* const iend = istart + srcSize;
|
BYTE const* const iend = istart + srcSize;
|
||||||
|
@ -620,7 +682,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
||||||
|
|
||||||
assert(rawSeqStore->pos <= rawSeqStore->size);
|
assert(rawSeqStore->pos <= rawSeqStore->size);
|
||||||
assert(rawSeqStore->size <= rawSeqStore->capacity);
|
assert(rawSeqStore->size <= rawSeqStore->capacity);
|
||||||
/* Loop through each sequence and apply the block compressor to the lits */
|
/* Loop through each sequence and apply the block compressor to the literals */
|
||||||
while (rawSeqStore->pos < rawSeqStore->size && ip < iend) {
|
while (rawSeqStore->pos < rawSeqStore->size && ip < iend) {
|
||||||
/* maybeSplitSequence updates rawSeqStore->pos */
|
/* maybeSplitSequence updates rawSeqStore->pos */
|
||||||
rawSeq const sequence = maybeSplitSequence(rawSeqStore,
|
rawSeq const sequence = maybeSplitSequence(rawSeqStore,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -66,6 +66,7 @@ size_t ZSTD_ldm_generateSequences(
|
||||||
*/
|
*/
|
||||||
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
||||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||||
|
ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
|
||||||
void const* src, size_t srcSize);
|
void const* src, size_t srcSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,7 +74,7 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
|
||||||
*
|
*
|
||||||
* Skip past `srcSize` bytes worth of sequences in `rawSeqStore`.
|
* Skip past `srcSize` bytes worth of sequences in `rawSeqStore`.
|
||||||
* Avoids emitting matches less than `minMatch` bytes.
|
* Avoids emitting matches less than `minMatch` bytes.
|
||||||
* Must be called for data with is not passed to ZSTD_ldm_blockCompress().
|
* Must be called for data that is not passed to ZSTD_ldm_blockCompress().
|
||||||
*/
|
*/
|
||||||
void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize,
|
void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize,
|
||||||
U32 const minMatch);
|
U32 const minMatch);
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||||||
|
* in the COPYING file in the root directory of this source tree).
|
||||||
|
* You may select, at your option, one of the above-listed licenses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZSTD_LDM_GEARTAB_H
|
||||||
|
#define ZSTD_LDM_GEARTAB_H
|
||||||
|
|
||||||
|
static U64 ZSTD_ldm_gearTab[256] = {
|
||||||
|
0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc,
|
||||||
|
0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05,
|
||||||
|
0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e,
|
||||||
|
0x9c8528f65badeaca, 0x86563706e2097529, 0x2902475fa375d889,
|
||||||
|
0xafb32a9739a5ebe6, 0xce2714da3883e639, 0x21eaf821722e69e,
|
||||||
|
0x37b628620b628, 0x49a8d455d88caf5, 0x8556d711e6958140,
|
||||||
|
0x4f7ae74fc605c1f, 0x829f0c3468bd3a20, 0x4ffdc885c625179e,
|
||||||
|
0x8473de048a3daf1b, 0x51008822b05646b2, 0x69d75d12b2d1cc5f,
|
||||||
|
0x8c9d4a19159154bc, 0xc3cc10f4abbd4003, 0xd06ddc1cecb97391,
|
||||||
|
0xbe48e6e7ed80302e, 0x3481db31cee03547, 0xacc3f67cdaa1d210,
|
||||||
|
0x65cb771d8c7f96cc, 0x8eb27177055723dd, 0xc789950d44cd94be,
|
||||||
|
0x934feadc3700b12b, 0x5e485f11edbdf182, 0x1e2e2a46fd64767a,
|
||||||
|
0x2969ca71d82efa7c, 0x9d46e9935ebbba2e, 0xe056b67e05e6822b,
|
||||||
|
0x94d73f55739d03a0, 0xcd7010bdb69b5a03, 0x455ef9fcd79b82f4,
|
||||||
|
0x869cb54a8749c161, 0x38d1a4fa6185d225, 0xb475166f94bbe9bb,
|
||||||
|
0xa4143548720959f1, 0x7aed4780ba6b26ba, 0xd0ce264439e02312,
|
||||||
|
0x84366d746078d508, 0xa8ce973c72ed17be, 0x21c323a29a430b01,
|
||||||
|
0x9962d617e3af80ee, 0xab0ce91d9c8cf75b, 0x530e8ee6d19a4dbc,
|
||||||
|
0x2ef68c0cf53f5d72, 0xc03a681640a85506, 0x496e4e9f9c310967,
|
||||||
|
0x78580472b59b14a0, 0x273824c23b388577, 0x66bf923ad45cb553,
|
||||||
|
0x47ae1a5a2492ba86, 0x35e304569e229659, 0x4765182a46870b6f,
|
||||||
|
0x6cbab625e9099412, 0xddac9a2e598522c1, 0x7172086e666624f2,
|
||||||
|
0xdf5003ca503b7837, 0x88c0c1db78563d09, 0x58d51865acfc289d,
|
||||||
|
0x177671aec65224f1, 0xfb79d8a241e967d7, 0x2be1e101cad9a49a,
|
||||||
|
0x6625682f6e29186b, 0x399553457ac06e50, 0x35dffb4c23abb74,
|
||||||
|
0x429db2591f54aade, 0xc52802a8037d1009, 0x6acb27381f0b25f3,
|
||||||
|
0xf45e2551ee4f823b, 0x8b0ea2d99580c2f7, 0x3bed519cbcb4e1e1,
|
||||||
|
0xff452823dbb010a, 0x9d42ed614f3dd267, 0x5b9313c06257c57b,
|
||||||
|
0xa114b8008b5e1442, 0xc1fe311c11c13d4b, 0x66e8763ea34c5568,
|
||||||
|
0x8b982af1c262f05d, 0xee8876faaa75fbb7, 0x8a62a4d0d172bb2a,
|
||||||
|
0xc13d94a3b7449a97, 0x6dbbba9dc15d037c, 0xc786101f1d92e0f1,
|
||||||
|
0xd78681a907a0b79b, 0xf61aaf2962c9abb9, 0x2cfd16fcd3cb7ad9,
|
||||||
|
0x868c5b6744624d21, 0x25e650899c74ddd7, 0xba042af4a7c37463,
|
||||||
|
0x4eb1a539465a3eca, 0xbe09dbf03b05d5ca, 0x774e5a362b5472ba,
|
||||||
|
0x47a1221229d183cd, 0x504b0ca18ef5a2df, 0xdffbdfbde2456eb9,
|
||||||
|
0x46cd2b2fbee34634, 0xf2aef8fe819d98c3, 0x357f5276d4599d61,
|
||||||
|
0x24a5483879c453e3, 0x88026889192b4b9, 0x28da96671782dbec,
|
||||||
|
0x4ef37c40588e9aaa, 0x8837b90651bc9fb3, 0xc164f741d3f0e5d6,
|
||||||
|
0xbc135a0a704b70ba, 0x69cd868f7622ada, 0xbc37ba89e0b9c0ab,
|
||||||
|
0x47c14a01323552f6, 0x4f00794bacee98bb, 0x7107de7d637a69d5,
|
||||||
|
0x88af793bb6f2255e, 0xf3c6466b8799b598, 0xc288c616aa7f3b59,
|
||||||
|
0x81ca63cf42fca3fd, 0x88d85ace36a2674b, 0xd056bd3792389e7,
|
||||||
|
0xe55c396c4e9dd32d, 0xbefb504571e6c0a6, 0x96ab32115e91e8cc,
|
||||||
|
0xbf8acb18de8f38d1, 0x66dae58801672606, 0x833b6017872317fb,
|
||||||
|
0xb87c16f2d1c92864, 0xdb766a74e58b669c, 0x89659f85c61417be,
|
||||||
|
0xc8daad856011ea0c, 0x76a4b565b6fe7eae, 0xa469d085f6237312,
|
||||||
|
0xaaf0365683a3e96c, 0x4dbb746f8424f7b8, 0x638755af4e4acc1,
|
||||||
|
0x3d7807f5bde64486, 0x17be6d8f5bbb7639, 0x903f0cd44dc35dc,
|
||||||
|
0x67b672eafdf1196c, 0xa676ff93ed4c82f1, 0x521d1004c5053d9d,
|
||||||
|
0x37ba9ad09ccc9202, 0x84e54d297aacfb51, 0xa0b4b776a143445,
|
||||||
|
0x820d471e20b348e, 0x1874383cb83d46dc, 0x97edeec7a1efe11c,
|
||||||
|
0xb330e50b1bdc42aa, 0x1dd91955ce70e032, 0xa514cdb88f2939d5,
|
||||||
|
0x2791233fd90db9d3, 0x7b670a4cc50f7a9b, 0x77c07d2a05c6dfa5,
|
||||||
|
0xe3778b6646d0a6fa, 0xb39c8eda47b56749, 0x933ed448addbef28,
|
||||||
|
0xaf846af6ab7d0bf4, 0xe5af208eb666e49, 0x5e6622f73534cd6a,
|
||||||
|
0x297daeca42ef5b6e, 0x862daef3d35539a6, 0xe68722498f8e1ea9,
|
||||||
|
0x981c53093dc0d572, 0xfa09b0bfbf86fbf5, 0x30b1e96166219f15,
|
||||||
|
0x70e7d466bdc4fb83, 0x5a66736e35f2a8e9, 0xcddb59d2b7c1baef,
|
||||||
|
0xd6c7d247d26d8996, 0xea4e39eac8de1ba3, 0x539c8bb19fa3aff2,
|
||||||
|
0x9f90e4c5fd508d8, 0xa34e5956fbaf3385, 0x2e2f8e151d3ef375,
|
||||||
|
0x173691e9b83faec1, 0xb85a8d56bf016379, 0x8382381267408ae3,
|
||||||
|
0xb90f901bbdc0096d, 0x7c6ad32933bcec65, 0x76bb5e2f2c8ad595,
|
||||||
|
0x390f851a6cf46d28, 0xc3e6064da1c2da72, 0xc52a0c101cfa5389,
|
||||||
|
0xd78eaf84a3fbc530, 0x3781b9e2288b997e, 0x73c2f6dea83d05c4,
|
||||||
|
0x4228e364c5b5ed7, 0x9d7a3edf0da43911, 0x8edcfeda24686756,
|
||||||
|
0x5e7667a7b7a9b3a1, 0x4c4f389fa143791d, 0xb08bc1023da7cddc,
|
||||||
|
0x7ab4be3ae529b1cc, 0x754e6132dbe74ff9, 0x71635442a839df45,
|
||||||
|
0x2f6fb1643fbe52de, 0x961e0a42cf7a8177, 0xf3b45d83d89ef2ea,
|
||||||
|
0xee3de4cf4a6e3e9b, 0xcd6848542c3295e7, 0xe4cee1664c78662f,
|
||||||
|
0x9947548b474c68c4, 0x25d73777a5ed8b0b, 0xc915b1d636b7fc,
|
||||||
|
0x21c2ba75d9b0d2da, 0x5f6b5dcf608a64a1, 0xdcf333255ff9570c,
|
||||||
|
0x633b922418ced4ee, 0xc136dde0b004b34a, 0x58cc83b05d4b2f5a,
|
||||||
|
0x5eb424dda28e42d2, 0x62df47369739cd98, 0xb4e0b42485e4ce17,
|
||||||
|
0x16e1f0c1f9a8d1e7, 0x8ec3916707560ebf, 0x62ba6e2df2cc9db3,
|
||||||
|
0xcbf9f4ff77d83a16, 0x78d9d7d07d2bbcc4, 0xef554ce1e02c41f4,
|
||||||
|
0x8d7581127eccf94d, 0xa9b53336cb3c8a05, 0x38c42c0bf45c4f91,
|
||||||
|
0x640893cdf4488863, 0x80ec34bc575ea568, 0x39f324f5b48eaa40,
|
||||||
|
0xe9d9ed1f8eff527f, 0x9224fc058cc5a214, 0xbaba00b04cfe7741,
|
||||||
|
0x309a9f120fcf52af, 0xa558f3ec65626212, 0x424bec8b7adabe2f,
|
||||||
|
0x41622513a6aea433, 0xb88da2d5324ca798, 0xd287733b245528a4,
|
||||||
|
0x9a44697e6d68aec3, 0x7b1093be2f49bb28, 0x50bbec632e3d8aad,
|
||||||
|
0x6cd90723e1ea8283, 0x897b9e7431b02bf3, 0x219efdcb338a7047,
|
||||||
|
0x3b0311f0a27c0656, 0xdb17bf91c0db96e7, 0x8cd4fd6b4e85a5b2,
|
||||||
|
0xfab071054ba6409d, 0x40d6fe831fa9dfd9, 0xaf358debad7d791e,
|
||||||
|
0xeb8d0e25a65e3e58, 0xbbcbd3df14e08580, 0xcf751f27ecdab2b,
|
||||||
|
0x2b4da14f2613d8f4
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ZSTD_LDM_GEARTAB_H */
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
|
* Copyright (c) Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -472,8 +472,6 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
|
||||||
ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams);
|
ZSTD_ldm_adjustParameters(¶ms.ldmParams, ¶ms.cParams);
|
||||||
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
|
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
|
||||||
assert(params.ldmParams.hashRateLog < 32);
|
assert(params.ldmParams.hashRateLog < 32);
|
||||||
serialState->ldmState.hashPower =
|
|
||||||
ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength);
|
|
||||||
} else {
|
} else {
|
||||||
ZSTD_memset(¶ms.ldmParams, 0, sizeof(params.ldmParams));
|
ZSTD_memset(¶ms.ldmParams, 0, sizeof(params.ldmParams));
|
||||||
}
|
}
|
||||||
|
@ -486,10 +484,10 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
|
||||||
size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);
|
size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);
|
||||||
unsigned const bucketLog =
|
unsigned const bucketLog =
|
||||||
params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;
|
params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;
|
||||||
size_t const bucketSize = (size_t)1 << bucketLog;
|
|
||||||
unsigned const prevBucketLog =
|
unsigned const prevBucketLog =
|
||||||
serialState->params.ldmParams.hashLog -
|
serialState->params.ldmParams.hashLog -
|
||||||
serialState->params.ldmParams.bucketSizeLog;
|
serialState->params.ldmParams.bucketSizeLog;
|
||||||
|
size_t const numBuckets = (size_t)1 << bucketLog;
|
||||||
/* Size the seq pool tables */
|
/* Size the seq pool tables */
|
||||||
ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
|
ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));
|
||||||
/* Reset the window */
|
/* Reset the window */
|
||||||
|
@ -501,20 +499,20 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
|
||||||
}
|
}
|
||||||
if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {
|
if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {
|
||||||
ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
|
ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);
|
||||||
serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(bucketSize, cMem);
|
serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem);
|
||||||
}
|
}
|
||||||
if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)
|
if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)
|
||||||
return 1;
|
return 1;
|
||||||
/* Zero the tables */
|
/* Zero the tables */
|
||||||
ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize);
|
ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize);
|
||||||
ZSTD_memset(serialState->ldmState.bucketOffsets, 0, bucketSize);
|
ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets);
|
||||||
|
|
||||||
/* Update window state and fill hash table with dict */
|
/* Update window state and fill hash table with dict */
|
||||||
serialState->ldmState.loadedDictEnd = 0;
|
serialState->ldmState.loadedDictEnd = 0;
|
||||||
if (dictSize > 0) {
|
if (dictSize > 0) {
|
||||||
if (dictContentType == ZSTD_dct_rawContent) {
|
if (dictContentType == ZSTD_dct_rawContent) {
|
||||||
BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
|
BYTE const* const dictEnd = (const BYTE*)dict + dictSize;
|
||||||
ZSTD_window_update(&serialState->ldmState.window, dict, dictSize);
|
ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0);
|
||||||
ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams);
|
ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, ¶ms.ldmParams);
|
||||||
serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
|
serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);
|
||||||
} else {
|
} else {
|
||||||
|
@ -571,7 +569,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
|
||||||
assert(seqStore.seq != NULL && seqStore.pos == 0 &&
|
assert(seqStore.seq != NULL && seqStore.pos == 0 &&
|
||||||
seqStore.size == 0 && seqStore.capacity > 0);
|
seqStore.size == 0 && seqStore.capacity > 0);
|
||||||
assert(src.size <= serialState->params.jobSize);
|
assert(src.size <= serialState->params.jobSize);
|
||||||
ZSTD_window_update(&serialState->ldmState.window, src.start, src.size);
|
ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0);
|
||||||
error = ZSTD_ldm_generateSequences(
|
error = ZSTD_ldm_generateSequences(
|
||||||
&serialState->ldmState, &seqStore,
|
&serialState->ldmState, &seqStore,
|
||||||
&serialState->params.ldmParams, src.start, src.size);
|
&serialState->params.ldmParams, src.start, src.size);
|
||||||
|
@ -683,6 +681,8 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
||||||
if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;
|
if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;
|
||||||
/* Don't run LDM for the chunks, since we handle it externally */
|
/* Don't run LDM for the chunks, since we handle it externally */
|
||||||
jobParams.ldmParams.enableLdm = 0;
|
jobParams.ldmParams.enableLdm = 0;
|
||||||
|
/* Correct nbWorkers to 0. */
|
||||||
|
jobParams.nbWorkers = 0;
|
||||||
|
|
||||||
|
|
||||||
/* init */
|
/* init */
|
||||||
|
@ -695,6 +695,10 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
||||||
{ size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
{ size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);
|
||||||
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
|
if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);
|
||||||
}
|
}
|
||||||
|
if (!job->firstJob) {
|
||||||
|
size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0);
|
||||||
|
if (ZSTD_isError(err)) JOB_ERROR(err);
|
||||||
|
}
|
||||||
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
|
{ size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,
|
||||||
job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
|
job->prefix.start, job->prefix.size, ZSTD_dct_rawContent, /* load dictionary in "content-only" mode (no header analysis) */
|
||||||
ZSTD_dtlm_fast,
|
ZSTD_dtlm_fast,
|
||||||
|
@ -750,6 +754,13 @@ static void ZSTDMT_compressionJob(void* jobDescription)
|
||||||
if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
|
if (ZSTD_isError(cSize)) JOB_ERROR(cSize);
|
||||||
lastCBlockSize = cSize;
|
lastCBlockSize = cSize;
|
||||||
} }
|
} }
|
||||||
|
if (!job->firstJob) {
|
||||||
|
/* Double check that we don't have an ext-dict, because then our
|
||||||
|
* repcode invalidation doesn't work.
|
||||||
|
*/
|
||||||
|
assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));
|
||||||
|
}
|
||||||
|
ZSTD_CCtx_trace(cctx, 0);
|
||||||
|
|
||||||
_endJob:
|
_endJob:
|
||||||
ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);
|
ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);
|
||||||
|
@ -1239,9 +1250,8 @@ size_t ZSTDMT_initCStream_internal(
|
||||||
|
|
||||||
if (params.rsyncable) {
|
if (params.rsyncable) {
|
||||||
/* Aim for the targetsectionSize as the average job size. */
|
/* Aim for the targetsectionSize as the average job size. */
|
||||||
U32 const jobSizeMB = (U32)(mtctx->targetSectionSize >> 20);
|
U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10);
|
||||||
U32 const rsyncBits = ZSTD_highbit32(jobSizeMB) + 20;
|
U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10);
|
||||||
assert(jobSizeMB >= 1);
|
|
||||||
DEBUGLOG(4, "rsyncLog = %u", rsyncBits);
|
DEBUGLOG(4, "rsyncLog = %u", rsyncBits);
|
||||||
mtctx->rsync.hash = 0;
|
mtctx->rsync.hash = 0;
|
||||||
mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;
|
mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -32,11 +32,11 @@
|
||||||
|
|
||||||
|
|
||||||
/* === Constants === */
|
/* === Constants === */
|
||||||
#ifndef ZSTDMT_NBWORKERS_MAX
|
#ifndef ZSTDMT_NBWORKERS_MAX /* a different value can be selected at compile time */
|
||||||
# define ZSTDMT_NBWORKERS_MAX 200
|
# define ZSTDMT_NBWORKERS_MAX ((sizeof(void*)==4) /*32-bit*/ ? 64 : 256)
|
||||||
#endif
|
#endif
|
||||||
#ifndef ZSTDMT_JOBSIZE_MIN
|
#ifndef ZSTDMT_JOBSIZE_MIN /* a different value can be selected at compile time */
|
||||||
# define ZSTDMT_JOBSIZE_MIN (1 MB)
|
# define ZSTDMT_JOBSIZE_MIN (512 KB)
|
||||||
#endif
|
#endif
|
||||||
#define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30)
|
#define ZSTDMT_JOBLOG_MAX (MEM_32bits() ? 29 : 30)
|
||||||
#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB))
|
#define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* ******************************************************************
|
/* ******************************************************************
|
||||||
* huff0 huffman decoder,
|
* huff0 huffman decoder,
|
||||||
* part of Finite State Entropy library
|
* part of Finite State Entropy library
|
||||||
* Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
*
|
*
|
||||||
* You can contact the author at :
|
* You can contact the author at :
|
||||||
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||||
|
@ -528,13 +528,15 @@ typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
|
||||||
static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,
|
static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,
|
||||||
const U32* rankValOrigin, const int minWeight,
|
const U32* rankValOrigin, const int minWeight,
|
||||||
const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
|
const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
|
||||||
U32 nbBitsBaseline, U16 baseSeq)
|
U32 nbBitsBaseline, U16 baseSeq, U32* wksp, size_t wkspSize)
|
||||||
{
|
{
|
||||||
HUF_DEltX2 DElt;
|
HUF_DEltX2 DElt;
|
||||||
U32 rankVal[HUF_TABLELOG_MAX + 1];
|
U32* rankVal = wksp;
|
||||||
|
|
||||||
|
assert(wkspSize >= HUF_TABLELOG_MAX + 1);
|
||||||
|
(void)wkspSize;
|
||||||
/* get pre-calculated rankVal */
|
/* get pre-calculated rankVal */
|
||||||
ZSTD_memcpy(rankVal, rankValOrigin, sizeof(rankVal));
|
ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
|
||||||
|
|
||||||
/* fill skipped values */
|
/* fill skipped values */
|
||||||
if (minWeight>1) {
|
if (minWeight>1) {
|
||||||
|
@ -569,14 +571,18 @@ static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 co
|
||||||
static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
|
static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
|
||||||
const sortedSymbol_t* sortedList, const U32 sortedListSize,
|
const sortedSymbol_t* sortedList, const U32 sortedListSize,
|
||||||
const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
|
const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
|
||||||
const U32 nbBitsBaseline)
|
const U32 nbBitsBaseline, U32* wksp, size_t wkspSize)
|
||||||
{
|
{
|
||||||
U32 rankVal[HUF_TABLELOG_MAX + 1];
|
U32* rankVal = wksp;
|
||||||
const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
|
const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
|
||||||
const U32 minBits = nbBitsBaseline - maxWeight;
|
const U32 minBits = nbBitsBaseline - maxWeight;
|
||||||
U32 s;
|
U32 s;
|
||||||
|
|
||||||
ZSTD_memcpy(rankVal, rankValOrigin, sizeof(rankVal));
|
assert(wkspSize >= HUF_TABLELOG_MAX + 1);
|
||||||
|
wksp += HUF_TABLELOG_MAX + 1;
|
||||||
|
wkspSize -= HUF_TABLELOG_MAX + 1;
|
||||||
|
|
||||||
|
ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
|
||||||
|
|
||||||
/* fill DTable */
|
/* fill DTable */
|
||||||
for (s=0; s<sortedListSize; s++) {
|
for (s=0; s<sortedListSize; s++) {
|
||||||
|
@ -594,7 +600,7 @@ static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
|
||||||
HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,
|
HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,
|
||||||
rankValOrigin[nbBits], minWeight,
|
rankValOrigin[nbBits], minWeight,
|
||||||
sortedList+sortedRank, sortedListSize-sortedRank,
|
sortedList+sortedRank, sortedListSize-sortedRank,
|
||||||
nbBitsBaseline, symbol);
|
nbBitsBaseline, symbol, wksp, wkspSize);
|
||||||
} else {
|
} else {
|
||||||
HUF_DEltX2 DElt;
|
HUF_DEltX2 DElt;
|
||||||
MEM_writeLE16(&(DElt.sequence), symbol);
|
MEM_writeLE16(&(DElt.sequence), symbol);
|
||||||
|
@ -608,6 +614,15 @@ static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
rankValCol_t rankVal[HUF_TABLELOG_MAX];
|
||||||
|
U32 rankStats[HUF_TABLELOG_MAX + 1];
|
||||||
|
U32 rankStart0[HUF_TABLELOG_MAX + 2];
|
||||||
|
sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];
|
||||||
|
BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];
|
||||||
|
U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
|
||||||
|
} HUF_ReadDTableX2_Workspace;
|
||||||
|
|
||||||
size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
|
size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
|
||||||
const void* src, size_t srcSize,
|
const void* src, size_t srcSize,
|
||||||
void* workSpace, size_t wkspSize)
|
void* workSpace, size_t wkspSize)
|
||||||
|
@ -620,47 +635,32 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
|
||||||
HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
|
HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
|
||||||
U32 *rankStart;
|
U32 *rankStart;
|
||||||
|
|
||||||
rankValCol_t* rankVal;
|
HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;
|
||||||
U32* rankStats;
|
|
||||||
U32* rankStart0;
|
|
||||||
sortedSymbol_t* sortedSymbol;
|
|
||||||
BYTE* weightList;
|
|
||||||
size_t spaceUsed32 = 0;
|
|
||||||
|
|
||||||
rankVal = (rankValCol_t *)((U32 *)workSpace + spaceUsed32);
|
if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);
|
||||||
spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;
|
|
||||||
rankStats = (U32 *)workSpace + spaceUsed32;
|
|
||||||
spaceUsed32 += HUF_TABLELOG_MAX + 1;
|
|
||||||
rankStart0 = (U32 *)workSpace + spaceUsed32;
|
|
||||||
spaceUsed32 += HUF_TABLELOG_MAX + 2;
|
|
||||||
sortedSymbol = (sortedSymbol_t *)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t);
|
|
||||||
spaceUsed32 += HUF_ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
|
|
||||||
weightList = (BYTE *)((U32 *)workSpace + spaceUsed32);
|
|
||||||
spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
|
|
||||||
|
|
||||||
if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);
|
rankStart = wksp->rankStart0 + 1;
|
||||||
|
ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));
|
||||||
rankStart = rankStart0 + 1;
|
ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));
|
||||||
ZSTD_memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
|
|
||||||
|
|
||||||
DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
|
DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
|
||||||
if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
||||||
/* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
|
/* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
|
||||||
|
|
||||||
iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);
|
iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), /* bmi2 */ 0);
|
||||||
if (HUF_isError(iSize)) return iSize;
|
if (HUF_isError(iSize)) return iSize;
|
||||||
|
|
||||||
/* check result */
|
/* check result */
|
||||||
if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
|
if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
|
||||||
|
|
||||||
/* find maxWeight */
|
/* find maxWeight */
|
||||||
for (maxW = tableLog; rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
|
for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
|
||||||
|
|
||||||
/* Get start index of each weight */
|
/* Get start index of each weight */
|
||||||
{ U32 w, nextRankStart = 0;
|
{ U32 w, nextRankStart = 0;
|
||||||
for (w=1; w<maxW+1; w++) {
|
for (w=1; w<maxW+1; w++) {
|
||||||
U32 curr = nextRankStart;
|
U32 curr = nextRankStart;
|
||||||
nextRankStart += rankStats[w];
|
nextRankStart += wksp->rankStats[w];
|
||||||
rankStart[w] = curr;
|
rankStart[w] = curr;
|
||||||
}
|
}
|
||||||
rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
|
rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
|
||||||
|
@ -670,37 +670,38 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
|
||||||
/* sort symbols by weight */
|
/* sort symbols by weight */
|
||||||
{ U32 s;
|
{ U32 s;
|
||||||
for (s=0; s<nbSymbols; s++) {
|
for (s=0; s<nbSymbols; s++) {
|
||||||
U32 const w = weightList[s];
|
U32 const w = wksp->weightList[s];
|
||||||
U32 const r = rankStart[w]++;
|
U32 const r = rankStart[w]++;
|
||||||
sortedSymbol[r].symbol = (BYTE)s;
|
wksp->sortedSymbol[r].symbol = (BYTE)s;
|
||||||
sortedSymbol[r].weight = (BYTE)w;
|
wksp->sortedSymbol[r].weight = (BYTE)w;
|
||||||
}
|
}
|
||||||
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
|
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build rankVal */
|
/* Build rankVal */
|
||||||
{ U32* const rankVal0 = rankVal[0];
|
{ U32* const rankVal0 = wksp->rankVal[0];
|
||||||
{ int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */
|
{ int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */
|
||||||
U32 nextRankVal = 0;
|
U32 nextRankVal = 0;
|
||||||
U32 w;
|
U32 w;
|
||||||
for (w=1; w<maxW+1; w++) {
|
for (w=1; w<maxW+1; w++) {
|
||||||
U32 curr = nextRankVal;
|
U32 curr = nextRankVal;
|
||||||
nextRankVal += rankStats[w] << (w+rescale);
|
nextRankVal += wksp->rankStats[w] << (w+rescale);
|
||||||
rankVal0[w] = curr;
|
rankVal0[w] = curr;
|
||||||
} }
|
} }
|
||||||
{ U32 const minBits = tableLog+1 - maxW;
|
{ U32 const minBits = tableLog+1 - maxW;
|
||||||
U32 consumed;
|
U32 consumed;
|
||||||
for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
|
for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
|
||||||
U32* const rankValPtr = rankVal[consumed];
|
U32* const rankValPtr = wksp->rankVal[consumed];
|
||||||
U32 w;
|
U32 w;
|
||||||
for (w = 1; w < maxW+1; w++) {
|
for (w = 1; w < maxW+1; w++) {
|
||||||
rankValPtr[w] = rankVal0[w] >> consumed;
|
rankValPtr[w] = rankVal0[w] >> consumed;
|
||||||
} } } }
|
} } } }
|
||||||
|
|
||||||
HUF_fillDTableX2(dt, maxTableLog,
|
HUF_fillDTableX2(dt, maxTableLog,
|
||||||
sortedSymbol, sizeOfSort,
|
wksp->sortedSymbol, sizeOfSort,
|
||||||
rankStart0, rankVal, maxW,
|
wksp->rankStart0, wksp->rankVal, maxW,
|
||||||
tableLog+1);
|
tableLog+1,
|
||||||
|
wksp->calleeWksp, sizeof(wksp->calleeWksp) / sizeof(U32));
|
||||||
|
|
||||||
dtd.tableLog = (BYTE)maxTableLog;
|
dtd.tableLog = (BYTE)maxTableLog;
|
||||||
dtd.tableType = 1;
|
dtd.tableType = 1;
|
||||||
|
@ -1225,7 +1226,7 @@ size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||||
HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
|
HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
|
||||||
return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
|
return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||||
size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
|
size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -62,6 +62,7 @@
|
||||||
#include "../common/fse.h"
|
#include "../common/fse.h"
|
||||||
#define HUF_STATIC_LINKING_ONLY
|
#define HUF_STATIC_LINKING_ONLY
|
||||||
#include "../common/huf.h"
|
#include "../common/huf.h"
|
||||||
|
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
||||||
#include "../common/zstd_internal.h" /* blockProperties_t */
|
#include "../common/zstd_internal.h" /* blockProperties_t */
|
||||||
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
||||||
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
|
||||||
|
@ -72,6 +73,144 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
* Multiple DDicts Hashset internals *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
|
||||||
|
#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
|
||||||
|
* Currently, that means a 0.75 load factor.
|
||||||
|
* So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
|
||||||
|
* the load factor of the ddict hash set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DDICT_HASHSET_TABLE_BASE_SIZE 64
|
||||||
|
#define DDICT_HASHSET_RESIZE_FACTOR 2
|
||||||
|
|
||||||
|
/* Hash function to determine starting position of dict insertion within the table
|
||||||
|
* Returns an index between [0, hashSet->ddictPtrTableSize]
|
||||||
|
*/
|
||||||
|
static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
||||||
|
const U64 hash = XXH64(&dictID, sizeof(U32), 0);
|
||||||
|
/* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
|
||||||
|
return hash & (hashSet->ddictPtrTableSize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adds DDict to a hashset without resizing it.
|
||||||
|
* If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
|
||||||
|
* Returns 0 if successful, or a zstd error code if something went wrong.
|
||||||
|
*/
|
||||||
|
static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
|
||||||
|
const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
|
||||||
|
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
||||||
|
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
||||||
|
RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
|
||||||
|
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
||||||
|
while (hashSet->ddictPtrTable[idx] != NULL) {
|
||||||
|
/* Replace existing ddict if inserting ddict with same dictID */
|
||||||
|
if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
|
||||||
|
DEBUGLOG(4, "DictID already exists, replacing rather than adding");
|
||||||
|
hashSet->ddictPtrTable[idx] = ddict;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
idx &= idxRangeMask;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
||||||
|
hashSet->ddictPtrTable[idx] = ddict;
|
||||||
|
hashSet->ddictPtrCount++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
|
||||||
|
* rehashes all values, allocates new table, frees old table.
|
||||||
|
* Returns 0 on success, otherwise a zstd error code.
|
||||||
|
*/
|
||||||
|
static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
||||||
|
size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
|
||||||
|
const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
|
||||||
|
const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
|
||||||
|
size_t oldTableSize = hashSet->ddictPtrTableSize;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
|
||||||
|
RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
|
||||||
|
hashSet->ddictPtrTable = newTable;
|
||||||
|
hashSet->ddictPtrTableSize = newTableSize;
|
||||||
|
hashSet->ddictPtrCount = 0;
|
||||||
|
for (i = 0; i < oldTableSize; ++i) {
|
||||||
|
if (oldTable[i] != NULL) {
|
||||||
|
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ZSTD_customFree((void*)oldTable, customMem);
|
||||||
|
DEBUGLOG(4, "Finished re-hash");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fetches a DDict with the given dictID
|
||||||
|
* Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
|
||||||
|
*/
|
||||||
|
static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
|
||||||
|
size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
|
||||||
|
const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
|
||||||
|
DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
|
||||||
|
for (;;) {
|
||||||
|
size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
|
||||||
|
if (currDictID == dictID || currDictID == 0) {
|
||||||
|
/* currDictID == 0 implies a NULL ddict entry */
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
idx &= idxRangeMask; /* Goes to start of table when we reach the end */
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
|
||||||
|
return hashSet->ddictPtrTable[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocates space for and returns a ddict hash set
|
||||||
|
* The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
|
||||||
|
* Returns NULL if allocation failed.
|
||||||
|
*/
|
||||||
|
static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
|
||||||
|
ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
|
||||||
|
DEBUGLOG(4, "Allocating new hash set");
|
||||||
|
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
|
||||||
|
ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
|
||||||
|
ret->ddictPtrCount = 0;
|
||||||
|
if (!ret || !ret->ddictPtrTable) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
|
||||||
|
* Note: The ZSTD_DDict* within the table are NOT freed.
|
||||||
|
*/
|
||||||
|
static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
|
||||||
|
DEBUGLOG(4, "Freeing ddict hash set");
|
||||||
|
if (hashSet && hashSet->ddictPtrTable) {
|
||||||
|
ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
|
||||||
|
}
|
||||||
|
if (hashSet) {
|
||||||
|
ZSTD_customFree(hashSet, customMem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
|
||||||
|
* Returns 0 on success, or a ZSTD error.
|
||||||
|
*/
|
||||||
|
static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
|
||||||
|
DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
|
||||||
|
if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
|
||||||
|
FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
|
||||||
|
}
|
||||||
|
FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*-*************************************************************
|
/*-*************************************************************
|
||||||
* Context management
|
* Context management
|
||||||
***************************************************************/
|
***************************************************************/
|
||||||
|
@ -101,6 +240,7 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
||||||
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
||||||
dctx->outBufferMode = ZSTD_bm_buffered;
|
dctx->outBufferMode = ZSTD_bm_buffered;
|
||||||
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
||||||
|
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
||||||
|
@ -120,8 +260,8 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
||||||
dctx->noForwardProgress = 0;
|
dctx->noForwardProgress = 0;
|
||||||
dctx->oversizedDuration = 0;
|
dctx->oversizedDuration = 0;
|
||||||
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
||||||
|
dctx->ddictSet = NULL;
|
||||||
ZSTD_DCtx_resetParameters(dctx);
|
ZSTD_DCtx_resetParameters(dctx);
|
||||||
dctx->validateChecksum = 1;
|
|
||||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||||
dctx->dictContentEndForFuzzing = NULL;
|
dctx->dictContentEndForFuzzing = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
@ -178,6 +318,10 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
||||||
if (dctx->legacyContext)
|
if (dctx->legacyContext)
|
||||||
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
||||||
#endif
|
#endif
|
||||||
|
if (dctx->ddictSet) {
|
||||||
|
ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
|
||||||
|
dctx->ddictSet = NULL;
|
||||||
|
}
|
||||||
ZSTD_customFree(dctx, cMem);
|
ZSTD_customFree(dctx, cMem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -190,6 +334,29 @@ void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
||||||
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
|
||||||
|
* the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
|
||||||
|
* accordingly sets the ddict to be used to decompress the frame.
|
||||||
|
*
|
||||||
|
* If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
|
||||||
|
*
|
||||||
|
* ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
|
||||||
|
*/
|
||||||
|
static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
|
||||||
|
assert(dctx->refMultipleDDicts && dctx->ddictSet);
|
||||||
|
DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
|
||||||
|
if (dctx->ddict) {
|
||||||
|
const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
|
||||||
|
if (frameDDict) {
|
||||||
|
DEBUGLOG(4, "DDict found!");
|
||||||
|
ZSTD_clearDict(dctx);
|
||||||
|
dctx->dictID = dctx->fParams.dictID;
|
||||||
|
dctx->ddict = frameDDict;
|
||||||
|
dctx->dictUses = ZSTD_use_indefinitely;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************************************
|
/*-*************************************************************
|
||||||
* Frame header decoding
|
* Frame header decoding
|
||||||
|
@ -441,12 +608,19 @@ unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
|
||||||
|
|
||||||
/** ZSTD_decodeFrameHeader() :
|
/** ZSTD_decodeFrameHeader() :
|
||||||
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
|
||||||
|
* If multiple DDict references are enabled, also will choose the correct DDict to use.
|
||||||
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
|
||||||
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
|
||||||
{
|
{
|
||||||
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
|
||||||
if (ZSTD_isError(result)) return result; /* invalid header */
|
if (ZSTD_isError(result)) return result; /* invalid header */
|
||||||
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
|
||||||
|
|
||||||
|
/* Reference DDict requested by frame if dctx references multiple ddicts */
|
||||||
|
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
|
||||||
|
ZSTD_DCtx_selectFrameDDict(dctx);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||||
/* Skip the dictID check in fuzzing mode, because it makes the search
|
/* Skip the dictID check in fuzzing mode, because it makes the search
|
||||||
* harder.
|
* harder.
|
||||||
|
@ -456,6 +630,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he
|
||||||
#endif
|
#endif
|
||||||
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
|
||||||
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);
|
||||||
|
dctx->processedCSize += headerSize;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,7 +753,7 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
||||||
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
|
||||||
{
|
{
|
||||||
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
|
||||||
ZSTD_checkContinuity(dctx, blockStart);
|
ZSTD_checkContinuity(dctx, blockStart, blockSize);
|
||||||
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
dctx->previousDstEnd = (const char*)blockStart + blockSize;
|
||||||
return blockSize;
|
return blockSize;
|
||||||
}
|
}
|
||||||
|
@ -610,6 +785,32 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
|
||||||
return regenSize;
|
return regenSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
|
||||||
|
{
|
||||||
|
#if ZSTD_TRACE
|
||||||
|
if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {
|
||||||
|
ZSTD_Trace trace;
|
||||||
|
ZSTD_memset(&trace, 0, sizeof(trace));
|
||||||
|
trace.version = ZSTD_VERSION_NUMBER;
|
||||||
|
trace.streaming = streaming;
|
||||||
|
if (dctx->ddict) {
|
||||||
|
trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);
|
||||||
|
trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);
|
||||||
|
trace.dictionaryIsCold = dctx->ddictIsCold;
|
||||||
|
}
|
||||||
|
trace.uncompressedSize = (size_t)uncompressedSize;
|
||||||
|
trace.compressedSize = (size_t)compressedSize;
|
||||||
|
trace.dctx = dctx;
|
||||||
|
ZSTD_trace_decompress_end(dctx->traceCtx, &trace);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)dctx;
|
||||||
|
(void)uncompressedSize;
|
||||||
|
(void)compressedSize;
|
||||||
|
(void)streaming;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! ZSTD_decompressFrame() :
|
/*! ZSTD_decompressFrame() :
|
||||||
* @dctx must be properly initialized
|
* @dctx must be properly initialized
|
||||||
|
@ -619,8 +820,9 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||||
void* dst, size_t dstCapacity,
|
void* dst, size_t dstCapacity,
|
||||||
const void** srcPtr, size_t *srcSizePtr)
|
const void** srcPtr, size_t *srcSizePtr)
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)(*srcPtr);
|
const BYTE* const istart = (const BYTE*)(*srcPtr);
|
||||||
BYTE* const ostart = (BYTE* const)dst;
|
const BYTE* ip = istart;
|
||||||
|
BYTE* const ostart = (BYTE*)dst;
|
||||||
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
|
||||||
BYTE* op = ostart;
|
BYTE* op = ostart;
|
||||||
size_t remainingSrcSize = *srcSizePtr;
|
size_t remainingSrcSize = *srcSizePtr;
|
||||||
|
@ -695,7 +897,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||||
ip += 4;
|
ip += 4;
|
||||||
remainingSrcSize -= 4;
|
remainingSrcSize -= 4;
|
||||||
}
|
}
|
||||||
|
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
||||||
/* Allow caller to get size read */
|
/* Allow caller to get size read */
|
||||||
*srcPtr = ip;
|
*srcPtr = ip;
|
||||||
*srcSizePtr = remainingSrcSize;
|
*srcSizePtr = remainingSrcSize;
|
||||||
|
@ -764,7 +966,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||||
* use this in all cases but ddict */
|
* use this in all cases but ddict */
|
||||||
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
|
||||||
}
|
}
|
||||||
ZSTD_checkContinuity(dctx, dst);
|
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
||||||
|
|
||||||
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
{ const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
|
||||||
&src, &srcSize);
|
&src, &srcSize);
|
||||||
|
@ -899,7 +1101,9 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||||
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
|
||||||
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
||||||
|
|
||||||
|
dctx->processedCSize += srcSize;
|
||||||
|
|
||||||
switch (dctx->stage)
|
switch (dctx->stage)
|
||||||
{
|
{
|
||||||
|
@ -1004,6 +1208,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||||
dctx->expected = 4;
|
dctx->expected = 4;
|
||||||
dctx->stage = ZSTDds_checkChecksum;
|
dctx->stage = ZSTDds_checkChecksum;
|
||||||
} else {
|
} else {
|
||||||
|
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
||||||
dctx->expected = 0; /* ends here */
|
dctx->expected = 0; /* ends here */
|
||||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||||
}
|
}
|
||||||
|
@ -1023,6 +1228,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||||
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
|
||||||
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
|
||||||
}
|
}
|
||||||
|
ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
|
||||||
dctx->expected = 0;
|
dctx->expected = 0;
|
||||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1176,8 +1382,12 @@ static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict
|
||||||
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
||||||
{
|
{
|
||||||
assert(dctx != NULL);
|
assert(dctx != NULL);
|
||||||
|
#if ZSTD_TRACE
|
||||||
|
dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;
|
||||||
|
#endif
|
||||||
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
|
||||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||||
|
dctx->processedCSize = 0;
|
||||||
dctx->decodedSize = 0;
|
dctx->decodedSize = 0;
|
||||||
dctx->previousDstEnd = NULL;
|
dctx->previousDstEnd = NULL;
|
||||||
dctx->prefixStart = NULL;
|
dctx->prefixStart = NULL;
|
||||||
|
@ -1391,6 +1601,16 @@ size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
|
||||||
if (ddict) {
|
if (ddict) {
|
||||||
dctx->ddict = ddict;
|
dctx->ddict = ddict;
|
||||||
dctx->dictUses = ZSTD_use_indefinitely;
|
dctx->dictUses = ZSTD_use_indefinitely;
|
||||||
|
if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
|
||||||
|
if (dctx->ddictSet == NULL) {
|
||||||
|
dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
|
||||||
|
if (!dctx->ddictSet) {
|
||||||
|
RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
|
||||||
|
FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1436,6 +1656,10 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
||||||
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
bounds.lowerBound = (int)ZSTD_d_validateChecksum;
|
||||||
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
|
||||||
return bounds;
|
return bounds;
|
||||||
|
case ZSTD_d_refMultipleDDicts:
|
||||||
|
bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
|
||||||
|
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
|
||||||
|
return bounds;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
bounds.error = ERROR(parameter_unsupported);
|
bounds.error = ERROR(parameter_unsupported);
|
||||||
|
@ -1473,6 +1697,9 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
|
||||||
case ZSTD_d_forceIgnoreChecksum:
|
case ZSTD_d_forceIgnoreChecksum:
|
||||||
*value = (int)dctx->forceIgnoreChecksum;
|
*value = (int)dctx->forceIgnoreChecksum;
|
||||||
return 0;
|
return 0;
|
||||||
|
case ZSTD_d_refMultipleDDicts:
|
||||||
|
*value = (int)dctx->refMultipleDDicts;
|
||||||
|
return 0;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
RETURN_ERROR(parameter_unsupported, "");
|
RETURN_ERROR(parameter_unsupported, "");
|
||||||
|
@ -1499,6 +1726,13 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
||||||
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
|
||||||
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
|
||||||
return 0;
|
return 0;
|
||||||
|
case ZSTD_d_refMultipleDDicts:
|
||||||
|
CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
|
||||||
|
if (dctx->staticSize != 0) {
|
||||||
|
RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
|
||||||
|
}
|
||||||
|
dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
|
||||||
|
return 0;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
RETURN_ERROR(parameter_unsupported, "");
|
RETURN_ERROR(parameter_unsupported, "");
|
||||||
|
@ -1680,6 +1914,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||||
} }
|
} }
|
||||||
#endif
|
#endif
|
||||||
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
{ size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
|
||||||
|
if (zds->refMultipleDDicts && zds->ddictSet) {
|
||||||
|
ZSTD_DCtx_selectFrameDDict(zds);
|
||||||
|
}
|
||||||
DEBUGLOG(5, "header size : %u", (U32)hSize);
|
DEBUGLOG(5, "header size : %u", (U32)hSize);
|
||||||
if (ZSTD_isError(hSize)) {
|
if (ZSTD_isError(hSize)) {
|
||||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -577,7 +577,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
|
||||||
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
|
||||||
const void* src, size_t srcSize)
|
const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
const BYTE* const istart = (const BYTE* const)src;
|
const BYTE* const istart = (const BYTE*)src;
|
||||||
const BYTE* const iend = istart + srcSize;
|
const BYTE* const iend = istart + srcSize;
|
||||||
const BYTE* ip = istart;
|
const BYTE* ip = istart;
|
||||||
int nbSeq;
|
int nbSeq;
|
||||||
|
@ -658,7 +658,6 @@ typedef struct {
|
||||||
size_t litLength;
|
size_t litLength;
|
||||||
size_t matchLength;
|
size_t matchLength;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
const BYTE* match;
|
|
||||||
} seq_t;
|
} seq_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -672,9 +671,6 @@ typedef struct {
|
||||||
ZSTD_fseState stateOffb;
|
ZSTD_fseState stateOffb;
|
||||||
ZSTD_fseState stateML;
|
ZSTD_fseState stateML;
|
||||||
size_t prevOffset[ZSTD_REP_NUM];
|
size_t prevOffset[ZSTD_REP_NUM];
|
||||||
const BYTE* prefixStart;
|
|
||||||
const BYTE* dictEnd;
|
|
||||||
size_t pos;
|
|
||||||
} seqState_t;
|
} seqState_t;
|
||||||
|
|
||||||
/*! ZSTD_overlapCopy8() :
|
/*! ZSTD_overlapCopy8() :
|
||||||
|
@ -936,10 +932,9 @@ ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD
|
||||||
: 0)
|
: 0)
|
||||||
|
|
||||||
typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
|
typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
|
||||||
typedef enum { ZSTD_p_noPrefetch=0, ZSTD_p_prefetch=1 } ZSTD_prefetch_e;
|
|
||||||
|
|
||||||
FORCE_INLINE_TEMPLATE seq_t
|
FORCE_INLINE_TEMPLATE seq_t
|
||||||
ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const ZSTD_prefetch_e prefetch)
|
ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
|
||||||
{
|
{
|
||||||
seq_t seq;
|
seq_t seq;
|
||||||
ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state];
|
ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state];
|
||||||
|
@ -1014,14 +1009,6 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c
|
||||||
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
|
DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
|
||||||
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
|
(U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
|
||||||
|
|
||||||
if (prefetch == ZSTD_p_prefetch) {
|
|
||||||
size_t const pos = seqState->pos + seq.litLength;
|
|
||||||
const BYTE* const matchBase = (seq.offset > pos) ? seqState->dictEnd : seqState->prefixStart;
|
|
||||||
seq.match = matchBase + pos - seq.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
|
|
||||||
* No consequence though : no memory access will occur, offset is only used for prefetching */
|
|
||||||
seqState->pos = pos + seq.matchLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ANS state update
|
/* ANS state update
|
||||||
* gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo().
|
* gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo().
|
||||||
* clang-9.2.0 does 7% worse with ZSTD_updateFseState().
|
* clang-9.2.0 does 7% worse with ZSTD_updateFseState().
|
||||||
|
@ -1108,7 +1095,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)seqStart;
|
const BYTE* ip = (const BYTE*)seqStart;
|
||||||
const BYTE* const iend = ip + seqSize;
|
const BYTE* const iend = ip + seqSize;
|
||||||
BYTE* const ostart = (BYTE* const)dst;
|
BYTE* const ostart = (BYTE*)dst;
|
||||||
BYTE* const oend = ostart + maxDstSize;
|
BYTE* const oend = ostart + maxDstSize;
|
||||||
BYTE* op = ostart;
|
BYTE* op = ostart;
|
||||||
const BYTE* litPtr = dctx->litPtr;
|
const BYTE* litPtr = dctx->litPtr;
|
||||||
|
@ -1122,7 +1109,6 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
||||||
/* Regen sequences */
|
/* Regen sequences */
|
||||||
if (nbSeq) {
|
if (nbSeq) {
|
||||||
seqState_t seqState;
|
seqState_t seqState;
|
||||||
size_t error = 0;
|
|
||||||
dctx->fseEntropy = 1;
|
dctx->fseEntropy = 1;
|
||||||
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
{ U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
||||||
RETURN_ERROR_IF(
|
RETURN_ERROR_IF(
|
||||||
|
@ -1156,13 +1142,14 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
||||||
* If you see most cycles served out of the DSB you've hit the good case.
|
* If you see most cycles served out of the DSB you've hit the good case.
|
||||||
* If it is pretty even then you may be in an okay case.
|
* If it is pretty even then you may be in an okay case.
|
||||||
*
|
*
|
||||||
* I've been able to reproduce this issue on the following CPUs:
|
* This issue has been reproduced on the following CPUs:
|
||||||
* - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9
|
* - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9
|
||||||
* Use Instruments->Counters to get DSB/MITE cycles.
|
* Use Instruments->Counters to get DSB/MITE cycles.
|
||||||
* I never got performance swings, but I was able to
|
* I never got performance swings, but I was able to
|
||||||
* go from the good case of mostly DSB to half of the
|
* go from the good case of mostly DSB to half of the
|
||||||
* cycles served from MITE.
|
* cycles served from MITE.
|
||||||
* - Coffeelake: Intel i9-9900k
|
* - Coffeelake: Intel i9-9900k
|
||||||
|
* - Coffeelake: Intel i7-9700k
|
||||||
*
|
*
|
||||||
* I haven't been able to reproduce the instability or DSB misses on any
|
* I haven't been able to reproduce the instability or DSB misses on any
|
||||||
* of the following CPUS:
|
* of the following CPUS:
|
||||||
|
@ -1175,33 +1162,35 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
|
||||||
*
|
*
|
||||||
* https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4
|
* https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4
|
||||||
*/
|
*/
|
||||||
|
__asm__(".p2align 6");
|
||||||
|
__asm__("nop");
|
||||||
__asm__(".p2align 5");
|
__asm__(".p2align 5");
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
|
# if __GNUC__ >= 9
|
||||||
|
/* better for gcc-9 and gcc-10, worse for clang and gcc-8 */
|
||||||
|
__asm__(".p2align 3");
|
||||||
|
# else
|
||||||
__asm__(".p2align 4");
|
__asm__(".p2align 4");
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
for ( ; ; ) {
|
for ( ; ; ) {
|
||||||
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_noPrefetch);
|
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
|
||||||
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
|
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
|
||||||
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
||||||
assert(!ZSTD_isError(oneSeqSize));
|
assert(!ZSTD_isError(oneSeqSize));
|
||||||
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
|
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
|
||||||
#endif
|
#endif
|
||||||
|
if (UNLIKELY(ZSTD_isError(oneSeqSize)))
|
||||||
|
return oneSeqSize;
|
||||||
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
|
DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
|
||||||
BIT_reloadDStream(&(seqState.DStream));
|
|
||||||
op += oneSeqSize;
|
op += oneSeqSize;
|
||||||
/* gcc and clang both don't like early returns in this loop.
|
if (UNLIKELY(!--nbSeq))
|
||||||
* Instead break and check for an error at the end of the loop.
|
|
||||||
*/
|
|
||||||
if (UNLIKELY(ZSTD_isError(oneSeqSize))) {
|
|
||||||
error = oneSeqSize;
|
|
||||||
break;
|
break;
|
||||||
}
|
BIT_reloadDStream(&(seqState.DStream));
|
||||||
if (UNLIKELY(!--nbSeq)) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if reached exact end */
|
/* check if reached exact end */
|
||||||
DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
|
DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
|
||||||
if (ZSTD_isError(error)) return error;
|
|
||||||
RETURN_ERROR_IF(nbSeq, corruption_detected, "");
|
RETURN_ERROR_IF(nbSeq, corruption_detected, "");
|
||||||
RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, "");
|
RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, "");
|
||||||
/* save reps for next block */
|
/* save reps for next block */
|
||||||
|
@ -1232,6 +1221,24 @@ ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
|
||||||
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
|
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
|
||||||
|
|
||||||
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
|
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
|
||||||
|
|
||||||
|
FORCE_INLINE_TEMPLATE size_t
|
||||||
|
ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,
|
||||||
|
const BYTE* const prefixStart, const BYTE* const dictEnd)
|
||||||
|
{
|
||||||
|
prefetchPos += sequence.litLength;
|
||||||
|
{ const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart;
|
||||||
|
const BYTE* const match = matchBase + prefetchPos - sequence.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
|
||||||
|
* No consequence though : memory address is only used for prefetching, not for dereferencing */
|
||||||
|
PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
||||||
|
}
|
||||||
|
return prefetchPos + sequence.matchLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This decoding function employs prefetching
|
||||||
|
* to reduce latency impact of cache misses.
|
||||||
|
* It's generally employed when block contains a significant portion of long-distance matches
|
||||||
|
* or when coupled with a "cold" dictionary */
|
||||||
FORCE_INLINE_TEMPLATE size_t
|
FORCE_INLINE_TEMPLATE size_t
|
||||||
ZSTD_decompressSequencesLong_body(
|
ZSTD_decompressSequencesLong_body(
|
||||||
ZSTD_DCtx* dctx,
|
ZSTD_DCtx* dctx,
|
||||||
|
@ -1242,7 +1249,7 @@ ZSTD_decompressSequencesLong_body(
|
||||||
{
|
{
|
||||||
const BYTE* ip = (const BYTE*)seqStart;
|
const BYTE* ip = (const BYTE*)seqStart;
|
||||||
const BYTE* const iend = ip + seqSize;
|
const BYTE* const iend = ip + seqSize;
|
||||||
BYTE* const ostart = (BYTE* const)dst;
|
BYTE* const ostart = (BYTE*)dst;
|
||||||
BYTE* const oend = ostart + maxDstSize;
|
BYTE* const oend = ostart + maxDstSize;
|
||||||
BYTE* op = ostart;
|
BYTE* op = ostart;
|
||||||
const BYTE* litPtr = dctx->litPtr;
|
const BYTE* litPtr = dctx->litPtr;
|
||||||
|
@ -1254,18 +1261,17 @@ ZSTD_decompressSequencesLong_body(
|
||||||
|
|
||||||
/* Regen sequences */
|
/* Regen sequences */
|
||||||
if (nbSeq) {
|
if (nbSeq) {
|
||||||
#define STORED_SEQS 4
|
#define STORED_SEQS 8
|
||||||
#define STORED_SEQS_MASK (STORED_SEQS-1)
|
#define STORED_SEQS_MASK (STORED_SEQS-1)
|
||||||
#define ADVANCED_SEQS 4
|
#define ADVANCED_SEQS STORED_SEQS
|
||||||
seq_t sequences[STORED_SEQS];
|
seq_t sequences[STORED_SEQS];
|
||||||
int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
|
int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
|
||||||
seqState_t seqState;
|
seqState_t seqState;
|
||||||
int seqNb;
|
int seqNb;
|
||||||
|
size_t prefetchPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */
|
||||||
|
|
||||||
dctx->fseEntropy = 1;
|
dctx->fseEntropy = 1;
|
||||||
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
|
||||||
seqState.prefixStart = prefixStart;
|
|
||||||
seqState.pos = (size_t)(op-prefixStart);
|
|
||||||
seqState.dictEnd = dictEnd;
|
|
||||||
assert(dst != NULL);
|
assert(dst != NULL);
|
||||||
assert(iend >= ip);
|
assert(iend >= ip);
|
||||||
RETURN_ERROR_IF(
|
RETURN_ERROR_IF(
|
||||||
|
@ -1277,21 +1283,23 @@ ZSTD_decompressSequencesLong_body(
|
||||||
|
|
||||||
/* prepare in advance */
|
/* prepare in advance */
|
||||||
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
|
for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
|
||||||
sequences[seqNb] = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
|
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
|
||||||
PREFETCH_L1(sequences[seqNb].match); PREFETCH_L1(sequences[seqNb].match + sequences[seqNb].matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
|
||||||
|
sequences[seqNb] = sequence;
|
||||||
}
|
}
|
||||||
RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, "");
|
RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, "");
|
||||||
|
|
||||||
/* decode and decompress */
|
/* decode and decompress */
|
||||||
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
|
for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
|
||||||
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, ZSTD_p_prefetch);
|
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
|
||||||
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
|
||||||
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
|
||||||
assert(!ZSTD_isError(oneSeqSize));
|
assert(!ZSTD_isError(oneSeqSize));
|
||||||
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
|
if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
|
||||||
#endif
|
#endif
|
||||||
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
|
||||||
PREFETCH_L1(sequence.match); PREFETCH_L1(sequence.match + sequence.matchLength - 1); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
|
|
||||||
|
prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
|
||||||
sequences[seqNb & STORED_SEQS_MASK] = sequence;
|
sequences[seqNb & STORED_SEQS_MASK] = sequence;
|
||||||
op += oneSeqSize;
|
op += oneSeqSize;
|
||||||
}
|
}
|
||||||
|
@ -1517,9 +1525,9 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
|
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)
|
||||||
{
|
{
|
||||||
if (dst != dctx->previousDstEnd) { /* not contiguous */
|
if (dst != dctx->previousDstEnd && dstSize > 0) { /* not contiguous */
|
||||||
dctx->dictEnd = dctx->previousDstEnd;
|
dctx->dictEnd = dctx->previousDstEnd;
|
||||||
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
|
||||||
dctx->prefixStart = dst;
|
dctx->prefixStart = dst;
|
||||||
|
@ -1533,7 +1541,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
|
||||||
const void* src, size_t srcSize)
|
const void* src, size_t srcSize)
|
||||||
{
|
{
|
||||||
size_t dSize;
|
size_t dSize;
|
||||||
ZSTD_checkContinuity(dctx, dst);
|
ZSTD_checkContinuity(dctx, dst, dstCapacity);
|
||||||
dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
|
dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
|
||||||
dctx->previousDstEnd = (char*)dst + dSize;
|
dctx->previousDstEnd = (char*)dst + dSize;
|
||||||
return dSize;
|
return dSize;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -99,6 +99,13 @@ typedef enum {
|
||||||
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
|
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
|
||||||
} ZSTD_dictUses_e;
|
} ZSTD_dictUses_e;
|
||||||
|
|
||||||
|
/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */
|
||||||
|
typedef struct {
|
||||||
|
const ZSTD_DDict** ddictPtrTable;
|
||||||
|
size_t ddictPtrTableSize;
|
||||||
|
size_t ddictPtrCount;
|
||||||
|
} ZSTD_DDictHashSet;
|
||||||
|
|
||||||
struct ZSTD_DCtx_s
|
struct ZSTD_DCtx_s
|
||||||
{
|
{
|
||||||
const ZSTD_seqSymbol* LLTptr;
|
const ZSTD_seqSymbol* LLTptr;
|
||||||
|
@ -113,6 +120,7 @@ struct ZSTD_DCtx_s
|
||||||
const void* dictEnd; /* end of previous segment */
|
const void* dictEnd; /* end of previous segment */
|
||||||
size_t expected;
|
size_t expected;
|
||||||
ZSTD_frameHeader fParams;
|
ZSTD_frameHeader fParams;
|
||||||
|
U64 processedCSize;
|
||||||
U64 decodedSize;
|
U64 decodedSize;
|
||||||
blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
|
blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
|
||||||
ZSTD_dStage stage;
|
ZSTD_dStage stage;
|
||||||
|
@ -136,6 +144,8 @@ struct ZSTD_DCtx_s
|
||||||
U32 dictID;
|
U32 dictID;
|
||||||
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
|
int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
|
||||||
ZSTD_dictUses_e dictUses;
|
ZSTD_dictUses_e dictUses;
|
||||||
|
ZSTD_DDictHashSet* ddictSet; /* Hash set for multiple ddicts */
|
||||||
|
ZSTD_refMultipleDDicts_e refMultipleDDicts; /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */
|
||||||
|
|
||||||
/* streaming */
|
/* streaming */
|
||||||
ZSTD_dStreamStage streamStage;
|
ZSTD_dStreamStage streamStage;
|
||||||
|
@ -166,6 +176,11 @@ struct ZSTD_DCtx_s
|
||||||
void const* dictContentBeginForFuzzing;
|
void const* dictContentBeginForFuzzing;
|
||||||
void const* dictContentEndForFuzzing;
|
void const* dictContentEndForFuzzing;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Tracing */
|
||||||
|
#if ZSTD_TRACE
|
||||||
|
ZSTD_TraceCtx traceCtx;
|
||||||
|
#endif
|
||||||
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
|
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,7 +199,7 @@ size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
||||||
* If yes, do nothing (continue on current segment).
|
* If yes, do nothing (continue on current segment).
|
||||||
* If not, classify previous segment as "external dictionary", and start a new segment.
|
* If not, classify previous segment as "external dictionary", and start a new segment.
|
||||||
* This function cannot fail. */
|
* This function cannot fail. */
|
||||||
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst);
|
void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize);
|
||||||
|
|
||||||
|
|
||||||
#endif /* ZSTD_DECOMPRESS_INTERNAL_H */
|
#endif /* ZSTD_DECOMPRESS_INTERNAL_H */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
||||||
|
@ -71,8 +71,8 @@ extern "C" {
|
||||||
|
|
||||||
/*------ Version ------*/
|
/*------ Version ------*/
|
||||||
#define ZSTD_VERSION_MAJOR 1
|
#define ZSTD_VERSION_MAJOR 1
|
||||||
#define ZSTD_VERSION_MINOR 4
|
#define ZSTD_VERSION_MINOR 5
|
||||||
#define ZSTD_VERSION_RELEASE 8
|
#define ZSTD_VERSION_RELEASE 0
|
||||||
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
|
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
|
||||||
|
|
||||||
/*! ZSTD_versionNumber() :
|
/*! ZSTD_versionNumber() :
|
||||||
|
@ -109,7 +109,6 @@ ZSTDLIB_API const char* ZSTD_versionString(void);
|
||||||
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
|
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Simple API
|
* Simple API
|
||||||
***************************************/
|
***************************************/
|
||||||
|
@ -166,7 +165,7 @@ ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t
|
||||||
* @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
|
* @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
|
||||||
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
|
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
|
||||||
|
|
||||||
/*! ZSTD_findFrameCompressedSize() :
|
/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+
|
||||||
* `src` should point to the start of a ZSTD frame or skippable frame.
|
* `src` should point to the start of a ZSTD frame or skippable frame.
|
||||||
* `srcSize` must be >= first frame size
|
* `srcSize` must be >= first frame size
|
||||||
* @return : the compressed size of the first frame starting at `src`,
|
* @return : the compressed size of the first frame starting at `src`,
|
||||||
|
@ -180,8 +179,9 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||||
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
|
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
|
||||||
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
|
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
|
||||||
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
|
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
|
||||||
ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */
|
ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed, requires v1.4.0+ */
|
||||||
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
|
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
|
||||||
|
ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
@ -199,7 +199,7 @@ ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compres
|
||||||
*/
|
*/
|
||||||
typedef struct ZSTD_CCtx_s ZSTD_CCtx;
|
typedef struct ZSTD_CCtx_s ZSTD_CCtx;
|
||||||
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
|
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
|
||||||
ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
|
ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* accept NULL pointer */
|
||||||
|
|
||||||
/*! ZSTD_compressCCtx() :
|
/*! ZSTD_compressCCtx() :
|
||||||
* Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
|
* Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
|
||||||
|
@ -222,7 +222,7 @@ ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
|
||||||
* Use one context per thread for parallel execution. */
|
* Use one context per thread for parallel execution. */
|
||||||
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||||
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
|
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
|
||||||
ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
|
ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */
|
||||||
|
|
||||||
/*! ZSTD_decompressDCtx() :
|
/*! ZSTD_decompressDCtx() :
|
||||||
* Same as ZSTD_decompress(),
|
* Same as ZSTD_decompress(),
|
||||||
|
@ -234,9 +234,9 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
|
||||||
const void* src, size_t srcSize);
|
const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/*********************************************
|
||||||
* Advanced compression API
|
* Advanced compression API (Requires v1.4.0+)
|
||||||
***************************************/
|
**********************************************/
|
||||||
|
|
||||||
/* API design :
|
/* API design :
|
||||||
* Parameters are pushed one by one into an existing context,
|
* Parameters are pushed one by one into an existing context,
|
||||||
|
@ -266,7 +266,6 @@ typedef enum { ZSTD_fast=1,
|
||||||
Only the order (from fast to strong) is guaranteed */
|
Only the order (from fast to strong) is guaranteed */
|
||||||
} ZSTD_strategy;
|
} ZSTD_strategy;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
||||||
/* compression parameters
|
/* compression parameters
|
||||||
|
@ -332,7 +331,6 @@ typedef enum {
|
||||||
* The higher the value of selected strategy, the more complex it is,
|
* The higher the value of selected strategy, the more complex it is,
|
||||||
* resulting in stronger and slower compression.
|
* resulting in stronger and slower compression.
|
||||||
* Special: value 0 means "use default strategy". */
|
* Special: value 0 means "use default strategy". */
|
||||||
|
|
||||||
/* LDM mode parameters */
|
/* LDM mode parameters */
|
||||||
ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.
|
ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.
|
||||||
* This parameter is designed to improve compression ratio
|
* This parameter is designed to improve compression ratio
|
||||||
|
@ -389,7 +387,7 @@ typedef enum {
|
||||||
ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
|
ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
|
||||||
* Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
|
* Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
|
||||||
* 0 means default, which is dynamically determined based on compression parameters.
|
* 0 means default, which is dynamically determined based on compression parameters.
|
||||||
* Job size must be a minimum of overlap size, or 1 MB, whichever is largest.
|
* Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest.
|
||||||
* The minimum size is automatically and transparently enforced. */
|
* The minimum size is automatically and transparently enforced. */
|
||||||
ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size.
|
ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size.
|
||||||
* The overlap size is an amount of data reloaded from previous job at the beginning of a new job.
|
* The overlap size is an amount of data reloaded from previous job at the beginning of a new job.
|
||||||
|
@ -419,6 +417,8 @@ typedef enum {
|
||||||
* ZSTD_c_stableOutBuffer
|
* ZSTD_c_stableOutBuffer
|
||||||
* ZSTD_c_blockDelimiters
|
* ZSTD_c_blockDelimiters
|
||||||
* ZSTD_c_validateSequences
|
* ZSTD_c_validateSequences
|
||||||
|
* ZSTD_c_splitBlocks
|
||||||
|
* ZSTD_c_useRowMatchFinder
|
||||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||||
* note : never ever use experimentalParam? names directly;
|
* note : never ever use experimentalParam? names directly;
|
||||||
* also, the enums values themselves are unstable and can still change.
|
* also, the enums values themselves are unstable and can still change.
|
||||||
|
@ -434,7 +434,10 @@ typedef enum {
|
||||||
ZSTD_c_experimentalParam9=1006,
|
ZSTD_c_experimentalParam9=1006,
|
||||||
ZSTD_c_experimentalParam10=1007,
|
ZSTD_c_experimentalParam10=1007,
|
||||||
ZSTD_c_experimentalParam11=1008,
|
ZSTD_c_experimentalParam11=1008,
|
||||||
ZSTD_c_experimentalParam12=1009
|
ZSTD_c_experimentalParam12=1009,
|
||||||
|
ZSTD_c_experimentalParam13=1010,
|
||||||
|
ZSTD_c_experimentalParam14=1011,
|
||||||
|
ZSTD_c_experimentalParam15=1012
|
||||||
} ZSTD_cParameter;
|
} ZSTD_cParameter;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -519,9 +522,9 @@ ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
|
||||||
const void* src, size_t srcSize);
|
const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***********************************************
|
||||||
* Advanced decompression API
|
* Advanced decompression API (Requires v1.4.0+)
|
||||||
***************************************/
|
************************************************/
|
||||||
|
|
||||||
/* The advanced API pushes parameters one by one into an existing DCtx context.
|
/* The advanced API pushes parameters one by one into an existing DCtx context.
|
||||||
* Parameters are sticky, and remain valid for all following frames
|
* Parameters are sticky, and remain valid for all following frames
|
||||||
|
@ -546,12 +549,14 @@ typedef enum {
|
||||||
* ZSTD_d_format
|
* ZSTD_d_format
|
||||||
* ZSTD_d_stableOutBuffer
|
* ZSTD_d_stableOutBuffer
|
||||||
* ZSTD_d_forceIgnoreChecksum
|
* ZSTD_d_forceIgnoreChecksum
|
||||||
|
* ZSTD_d_refMultipleDDicts
|
||||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||||
* note : never ever use experimentalParam? names directly
|
* note : never ever use experimentalParam? names directly
|
||||||
*/
|
*/
|
||||||
ZSTD_d_experimentalParam1=1000,
|
ZSTD_d_experimentalParam1=1000,
|
||||||
ZSTD_d_experimentalParam2=1001,
|
ZSTD_d_experimentalParam2=1001,
|
||||||
ZSTD_d_experimentalParam3=1002
|
ZSTD_d_experimentalParam3=1002,
|
||||||
|
ZSTD_d_experimentalParam4=1003
|
||||||
|
|
||||||
} ZSTD_dParameter;
|
} ZSTD_dParameter;
|
||||||
|
|
||||||
|
@ -665,7 +670,7 @@ typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same
|
||||||
/* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
|
/* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
|
||||||
/*===== ZSTD_CStream management functions =====*/
|
/*===== ZSTD_CStream management functions =====*/
|
||||||
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
|
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
|
||||||
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
|
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); /* accept NULL pointer */
|
||||||
|
|
||||||
/*===== Streaming compression functions =====*/
|
/*===== Streaming compression functions =====*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -681,7 +686,7 @@ typedef enum {
|
||||||
: note : multithreaded compression will block to flush as much output as possible. */
|
: note : multithreaded compression will block to flush as much output as possible. */
|
||||||
} ZSTD_EndDirective;
|
} ZSTD_EndDirective;
|
||||||
|
|
||||||
/*! ZSTD_compressStream2() :
|
/*! ZSTD_compressStream2() : Requires v1.4.0+
|
||||||
* Behaves about the same as ZSTD_compressStream, with additional control on end directive.
|
* Behaves about the same as ZSTD_compressStream, with additional control on end directive.
|
||||||
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
|
||||||
* - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
|
* - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
|
||||||
|
@ -727,11 +732,11 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
|
||||||
|
|
||||||
|
|
||||||
/* *****************************************************************************
|
/* *****************************************************************************
|
||||||
* This following is a legacy streaming API.
|
* This following is a legacy streaming API, available since v1.0+ .
|
||||||
* It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().
|
* It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().
|
||||||
* It is redundant, but remains fully supported.
|
* It is redundant, but remains fully supported.
|
||||||
* Advanced parameters and dictionary compression can only be used through the
|
* Streaming in combination with advanced parameters and dictionary compression
|
||||||
* new API.
|
* can only be used through the new API.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -786,7 +791,7 @@ typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same
|
||||||
/* For compatibility with versions <= v1.2.0, prefer differentiating them. */
|
/* For compatibility with versions <= v1.2.0, prefer differentiating them. */
|
||||||
/*===== ZSTD_DStream management functions =====*/
|
/*===== ZSTD_DStream management functions =====*/
|
||||||
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
|
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
|
||||||
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
|
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* accept NULL pointer */
|
||||||
|
|
||||||
/*===== Streaming decompression functions =====*/
|
/*===== Streaming decompression functions =====*/
|
||||||
|
|
||||||
|
@ -809,7 +814,7 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
|
||||||
/*! ZSTD_compress_usingDict() :
|
/*! ZSTD_compress_usingDict() :
|
||||||
* Compression at an explicit compression level using a Dictionary.
|
* Compression at an explicit compression level using a Dictionary.
|
||||||
* A dictionary can be any arbitrary data segment (also called a prefix),
|
* A dictionary can be any arbitrary data segment (also called a prefix),
|
||||||
* or a buffer with specified information (see dictBuilder/zdict.h).
|
* or a buffer with specified information (see zdict.h).
|
||||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||||
* It's intended for a dictionary used only once.
|
* It's intended for a dictionary used only once.
|
||||||
* Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
* Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||||
|
@ -852,7 +857,8 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize
|
||||||
int compressionLevel);
|
int compressionLevel);
|
||||||
|
|
||||||
/*! ZSTD_freeCDict() :
|
/*! ZSTD_freeCDict() :
|
||||||
* Function frees memory allocated by ZSTD_createCDict(). */
|
* Function frees memory allocated by ZSTD_createCDict().
|
||||||
|
* If a NULL pointer is passed, no operation is performed. */
|
||||||
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
|
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
|
||||||
|
|
||||||
/*! ZSTD_compress_usingCDict() :
|
/*! ZSTD_compress_usingCDict() :
|
||||||
|
@ -874,7 +880,8 @@ typedef struct ZSTD_DDict_s ZSTD_DDict;
|
||||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
||||||
|
|
||||||
/*! ZSTD_freeDDict() :
|
/*! ZSTD_freeDDict() :
|
||||||
* Function frees memory allocated with ZSTD_createDDict() */
|
* Function frees memory allocated with ZSTD_createDDict()
|
||||||
|
* If a NULL pointer is passed, no operation is performed. */
|
||||||
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
|
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
|
||||||
|
|
||||||
/*! ZSTD_decompress_usingDDict() :
|
/*! ZSTD_decompress_usingDDict() :
|
||||||
|
@ -890,19 +897,25 @@ ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
||||||
* Dictionary helper functions
|
* Dictionary helper functions
|
||||||
*******************************/
|
*******************************/
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromDict() :
|
/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+
|
||||||
* Provides the dictID stored within dictionary.
|
* Provides the dictID stored within dictionary.
|
||||||
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
||||||
* It can still be loaded, but as a content-only dictionary. */
|
* It can still be loaded, but as a content-only dictionary. */
|
||||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromDDict() :
|
/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+
|
||||||
|
* Provides the dictID of the dictionary loaded into `cdict`.
|
||||||
|
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
||||||
|
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
||||||
|
ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);
|
||||||
|
|
||||||
|
/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+
|
||||||
* Provides the dictID of the dictionary loaded into `ddict`.
|
* Provides the dictID of the dictionary loaded into `ddict`.
|
||||||
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
||||||
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
||||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromFrame() :
|
/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+
|
||||||
* Provides the dictID required to decompressed the frame stored within `src`.
|
* Provides the dictID required to decompressed the frame stored within `src`.
|
||||||
* If @return == 0, the dictID could not be decoded.
|
* If @return == 0, the dictID could not be decoded.
|
||||||
* This could for one of the following reasons :
|
* This could for one of the following reasons :
|
||||||
|
@ -916,7 +929,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Advanced dictionary and prefix API
|
* Advanced dictionary and prefix API (Requires v1.4.0+)
|
||||||
*
|
*
|
||||||
* This API allows dictionaries to be used with ZSTD_compress2(),
|
* This API allows dictionaries to be used with ZSTD_compress2(),
|
||||||
* ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
|
* ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
|
||||||
|
@ -925,7 +938,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/*! ZSTD_CCtx_loadDictionary() :
|
/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+
|
||||||
* Create an internal CDict from `dict` buffer.
|
* Create an internal CDict from `dict` buffer.
|
||||||
* Decompression will have to use same dictionary.
|
* Decompression will have to use same dictionary.
|
||||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||||
|
@ -944,11 +957,11 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||||
* to precisely select how dictionary content must be interpreted. */
|
* to precisely select how dictionary content must be interpreted. */
|
||||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||||
|
|
||||||
/*! ZSTD_CCtx_refCDict() :
|
/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+
|
||||||
* Reference a prepared dictionary, to be used for all next compressed frames.
|
* Reference a prepared dictionary, to be used for all next compressed frames.
|
||||||
* Note that compression parameters are enforced from within CDict,
|
* Note that compression parameters are enforced from within CDict,
|
||||||
* and supersede any compression parameter previously set within CCtx.
|
* and supersede any compression parameter previously set within CCtx.
|
||||||
* The parameters ignored are labled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
|
* The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
|
||||||
* The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
|
* The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
|
||||||
* The dictionary will remain valid for future compressed frames using same CCtx.
|
* The dictionary will remain valid for future compressed frames using same CCtx.
|
||||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||||
|
@ -958,7 +971,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, s
|
||||||
* Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */
|
* Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */
|
||||||
ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
||||||
|
|
||||||
/*! ZSTD_CCtx_refPrefix() :
|
/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+
|
||||||
* Reference a prefix (single-usage dictionary) for next compressed frame.
|
* Reference a prefix (single-usage dictionary) for next compressed frame.
|
||||||
* A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
|
* A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
|
||||||
* Decompression will need same prefix to properly regenerate data.
|
* Decompression will need same prefix to properly regenerate data.
|
||||||
|
@ -979,7 +992,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
||||||
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
|
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
|
||||||
const void* prefix, size_t prefixSize);
|
const void* prefix, size_t prefixSize);
|
||||||
|
|
||||||
/*! ZSTD_DCtx_loadDictionary() :
|
/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+
|
||||||
* Create an internal DDict from dict buffer,
|
* Create an internal DDict from dict buffer,
|
||||||
* to be used to decompress next frames.
|
* to be used to decompress next frames.
|
||||||
* The dictionary remains valid for all future frames, until explicitly invalidated.
|
* The dictionary remains valid for all future frames, until explicitly invalidated.
|
||||||
|
@ -996,9 +1009,16 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
|
||||||
|
|
||||||
/*! ZSTD_DCtx_refDDict() :
|
/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+
|
||||||
* Reference a prepared dictionary, to be used to decompress next frames.
|
* Reference a prepared dictionary, to be used to decompress next frames.
|
||||||
* The dictionary remains active for decompression of future frames using same DCtx.
|
* The dictionary remains active for decompression of future frames using same DCtx.
|
||||||
|
*
|
||||||
|
* If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function
|
||||||
|
* will store the DDict references in a table, and the DDict used for decompression
|
||||||
|
* will be determined at decompression time, as per the dict ID in the frame.
|
||||||
|
* The memory for the table is allocated on the first call to refDDict, and can be
|
||||||
|
* freed with ZSTD_freeDCtx().
|
||||||
|
*
|
||||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||||
* Note 1 : Currently, only one dictionary can be managed.
|
* Note 1 : Currently, only one dictionary can be managed.
|
||||||
* Referencing a new dictionary effectively "discards" any previous one.
|
* Referencing a new dictionary effectively "discards" any previous one.
|
||||||
|
@ -1007,7 +1027,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, s
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
|
ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
|
||||||
|
|
||||||
/*! ZSTD_DCtx_refPrefix() :
|
/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+
|
||||||
* Reference a prefix (single-usage dictionary) to decompress next frame.
|
* Reference a prefix (single-usage dictionary) to decompress next frame.
|
||||||
* This is the reverse operation of ZSTD_CCtx_refPrefix(),
|
* This is the reverse operation of ZSTD_CCtx_refPrefix(),
|
||||||
* and must use the same prefix as the one used during compression.
|
* and must use the same prefix as the one used during compression.
|
||||||
|
@ -1028,7 +1048,7 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,
|
||||||
|
|
||||||
/* === Memory management === */
|
/* === Memory management === */
|
||||||
|
|
||||||
/*! ZSTD_sizeof_*() :
|
/*! ZSTD_sizeof_*() : Requires v1.4.0+
|
||||||
* These functions give the _current_ memory usage of selected object.
|
* These functions give the _current_ memory usage of selected object.
|
||||||
* Note that object memory usage can evolve (increase or decrease) over time. */
|
* Note that object memory usage can evolve (increase or decrease) over time. */
|
||||||
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
|
||||||
|
@ -1053,6 +1073,28 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||||
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
|
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
|
||||||
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
|
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
|
||||||
|
|
||||||
|
/* Deprecation warnings :
|
||||||
|
* Should these warnings be a problem, it is generally possible to disable them,
|
||||||
|
* typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||||
|
* Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS.
|
||||||
|
*/
|
||||||
|
#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS
|
||||||
|
# define ZSTD_DEPRECATED(message) ZSTDLIB_API /* disable deprecation warnings */
|
||||||
|
#else
|
||||||
|
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||||
|
# define ZSTD_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API
|
||||||
|
# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__)
|
||||||
|
# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message)))
|
||||||
|
# elif defined(__GNUC__) && (__GNUC__ >= 3)
|
||||||
|
# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated))
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# define ZSTD_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message))
|
||||||
|
# else
|
||||||
|
# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler")
|
||||||
|
# define ZSTD_DEPRECATED(message) ZSTDLIB_API
|
||||||
|
# endif
|
||||||
|
#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */
|
||||||
|
|
||||||
/****************************************************************************************
|
/****************************************************************************************
|
||||||
* experimental API (static linking only)
|
* experimental API (static linking only)
|
||||||
****************************************************************************************
|
****************************************************************************************
|
||||||
|
@ -1205,6 +1247,12 @@ typedef enum {
|
||||||
ZSTD_d_ignoreChecksum = 1
|
ZSTD_d_ignoreChecksum = 1
|
||||||
} ZSTD_forceIgnoreChecksum_e;
|
} ZSTD_forceIgnoreChecksum_e;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Note: this enum controls ZSTD_d_refMultipleDDicts */
|
||||||
|
ZSTD_rmd_refSingleDDict = 0,
|
||||||
|
ZSTD_rmd_refMultipleDDicts = 1
|
||||||
|
} ZSTD_refMultipleDDicts_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* Note: this enum and the behavior it controls are effectively internal
|
/* Note: this enum and the behavior it controls are effectively internal
|
||||||
* implementation details of the compressor. They are expected to continue
|
* implementation details of the compressor. They are expected to continue
|
||||||
|
@ -1253,6 +1301,11 @@ typedef enum {
|
||||||
ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */
|
ZSTD_lcm_uncompressed = 2 /**< Always emit uncompressed literals. */
|
||||||
} ZSTD_literalCompressionMode_e;
|
} ZSTD_literalCompressionMode_e;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ZSTD_urm_auto = 0, /* Automatically determine whether or not we use row matchfinder */
|
||||||
|
ZSTD_urm_disableRowMatchFinder = 1, /* Never use row matchfinder */
|
||||||
|
ZSTD_urm_enableRowMatchFinder = 2 /* Always use row matchfinder when applicable */
|
||||||
|
} ZSTD_useRowMatchFinderMode_e;
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Frame size functions
|
* Frame size functions
|
||||||
|
@ -1286,7 +1339,7 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t
|
||||||
* `srcSize` must be the _exact_ size of this series
|
* `srcSize` must be the _exact_ size of this series
|
||||||
* (i.e. there should be a frame boundary at `src + srcSize`)
|
* (i.e. there should be a frame boundary at `src + srcSize`)
|
||||||
* @return : - upper-bound for the decompressed size of all data in all successive frames
|
* @return : - upper-bound for the decompressed size of all data in all successive frames
|
||||||
* - if an error occured: ZSTD_CONTENTSIZE_ERROR
|
* - if an error occurred: ZSTD_CONTENTSIZE_ERROR
|
||||||
*
|
*
|
||||||
* note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
|
* note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
|
||||||
* note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
|
* note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
|
||||||
|
@ -1372,6 +1425,23 @@ ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size
|
||||||
const void* src, size_t srcSize);
|
const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
|
||||||
|
/*! ZSTD_writeSkippableFrame() :
|
||||||
|
* Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.
|
||||||
|
*
|
||||||
|
* Skippable frames begin with a a 4-byte magic number. There are 16 possible choices of magic number,
|
||||||
|
* ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.
|
||||||
|
* As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so
|
||||||
|
* the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.
|
||||||
|
*
|
||||||
|
* Returns an error if destination buffer is not large enough, if the source size is not representable
|
||||||
|
* with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).
|
||||||
|
*
|
||||||
|
* @return : number of bytes written or a ZSTD error.
|
||||||
|
*/
|
||||||
|
ZSTDLIB_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
|
||||||
|
const void* src, size_t srcSize, unsigned magicVariant);
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Memory management
|
* Memory management
|
||||||
***************************************/
|
***************************************/
|
||||||
|
@ -1506,13 +1576,14 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictS
|
||||||
* Note that the lifetime of such pool must exist while being used.
|
* Note that the lifetime of such pool must exist while being used.
|
||||||
* ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
|
* ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
|
||||||
* to use an internal thread pool).
|
* to use an internal thread pool).
|
||||||
* ZSTD_freeThreadPool frees a thread pool.
|
* ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
|
||||||
*/
|
*/
|
||||||
typedef struct POOL_ctx_s ZSTD_threadPool;
|
typedef struct POOL_ctx_s ZSTD_threadPool;
|
||||||
ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
|
ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
|
||||||
ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool);
|
ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */
|
||||||
ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
|
ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This API is temporary and is expected to change or disappear in the future!
|
* This API is temporary and is expected to change or disappear in the future!
|
||||||
*/
|
*/
|
||||||
|
@ -1523,10 +1594,12 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
|
||||||
const ZSTD_CCtx_params* cctxParams,
|
const ZSTD_CCtx_params* cctxParams,
|
||||||
ZSTD_customMem customMem);
|
ZSTD_customMem customMem);
|
||||||
|
|
||||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
|
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(
|
||||||
ZSTD_dictLoadMethod_e dictLoadMethod,
|
const void* dict, size_t dictSize,
|
||||||
ZSTD_dictContentType_e dictContentType,
|
ZSTD_dictLoadMethod_e dictLoadMethod,
|
||||||
ZSTD_customMem customMem);
|
ZSTD_dictContentType_e dictContentType,
|
||||||
|
ZSTD_customMem customMem);
|
||||||
|
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
* Advanced compression functions
|
* Advanced compression functions
|
||||||
|
@ -1540,12 +1613,6 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictS
|
||||||
* note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */
|
* note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */
|
||||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||||
|
|
||||||
/*! ZSTD_getDictID_fromCDict() :
|
|
||||||
* Provides the dictID of the dictionary loaded into `cdict`.
|
|
||||||
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
|
|
||||||
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
|
|
||||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);
|
|
||||||
|
|
||||||
/*! ZSTD_getCParams() :
|
/*! ZSTD_getCParams() :
|
||||||
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||||
* `estimatedSrcSize` value is optional, select 0 if not known */
|
* `estimatedSrcSize` value is optional, select 0 if not known */
|
||||||
|
@ -1572,18 +1639,20 @@ ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParame
|
||||||
/*! ZSTD_compress_advanced() :
|
/*! ZSTD_compress_advanced() :
|
||||||
* Note : this function is now DEPRECATED.
|
* Note : this function is now DEPRECATED.
|
||||||
* It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.
|
* It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.
|
||||||
* This prototype will be marked as deprecated and generate compilation warning on reaching v1.5.x */
|
* This prototype will generate compilation warnings. */
|
||||||
ZSTDLIB_API size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
|
ZSTD_DEPRECATED("use ZSTD_compress2")
|
||||||
|
size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
|
||||||
void* dst, size_t dstCapacity,
|
void* dst, size_t dstCapacity,
|
||||||
const void* src, size_t srcSize,
|
const void* src, size_t srcSize,
|
||||||
const void* dict,size_t dictSize,
|
const void* dict,size_t dictSize,
|
||||||
ZSTD_parameters params);
|
ZSTD_parameters params);
|
||||||
|
|
||||||
/*! ZSTD_compress_usingCDict_advanced() :
|
/*! ZSTD_compress_usingCDict_advanced() :
|
||||||
* Note : this function is now REDUNDANT.
|
* Note : this function is now DEPRECATED.
|
||||||
* It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.
|
* It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.
|
||||||
* This prototype will be marked as deprecated and generate compilation warning in some future version */
|
* This prototype will generate compilation warnings. */
|
||||||
ZSTDLIB_API size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
ZSTD_DEPRECATED("use ZSTD_compress2 with ZSTD_CCtx_loadDictionary")
|
||||||
|
size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
|
||||||
void* dst, size_t dstCapacity,
|
void* dst, size_t dstCapacity,
|
||||||
const void* src, size_t srcSize,
|
const void* src, size_t srcSize,
|
||||||
const ZSTD_CDict* cdict,
|
const ZSTD_CDict* cdict,
|
||||||
|
@ -1645,7 +1714,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
|
||||||
|
|
||||||
/* Controls how the literals are compressed (default is auto).
|
/* Controls how the literals are compressed (default is auto).
|
||||||
* The value must be of type ZSTD_literalCompressionMode_e.
|
* The value must be of type ZSTD_literalCompressionMode_e.
|
||||||
* See ZSTD_literalCompressionMode_t enum definition for details.
|
* See ZSTD_literalCompressionMode_e enum definition for details.
|
||||||
*/
|
*/
|
||||||
#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
|
#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
|
||||||
|
|
||||||
|
@ -1797,12 +1866,52 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
|
||||||
*/
|
*/
|
||||||
#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12
|
#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12
|
||||||
|
|
||||||
|
/* ZSTD_c_splitBlocks
|
||||||
|
* Default is 0 == disabled. Set to 1 to enable block splitting.
|
||||||
|
*
|
||||||
|
* Will attempt to split blocks in order to improve compression ratio at the cost of speed.
|
||||||
|
*/
|
||||||
|
#define ZSTD_c_splitBlocks ZSTD_c_experimentalParam13
|
||||||
|
|
||||||
|
/* ZSTD_c_useRowMatchFinder
|
||||||
|
* Default is ZSTD_urm_auto.
|
||||||
|
* Controlled with ZSTD_useRowMatchFinderMode_e enum.
|
||||||
|
*
|
||||||
|
* By default, in ZSTD_urm_auto, when finalizing the compression parameters, the library
|
||||||
|
* will decide at runtime whether to use the row-based matchfinder based on support for SIMD
|
||||||
|
* instructions as well as the windowLog.
|
||||||
|
*
|
||||||
|
* Set to ZSTD_urm_disableRowMatchFinder to never use row-based matchfinder.
|
||||||
|
* Set to ZSTD_urm_enableRowMatchFinder to force usage of row-based matchfinder.
|
||||||
|
*/
|
||||||
|
#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14
|
||||||
|
|
||||||
|
/* ZSTD_c_deterministicRefPrefix
|
||||||
|
* Default is 0 == disabled. Set to 1 to enable.
|
||||||
|
*
|
||||||
|
* Zstd produces different results for prefix compression when the prefix is
|
||||||
|
* directly adjacent to the data about to be compressed vs. when it isn't.
|
||||||
|
* This is because zstd detects that the two buffers are contiguous and it can
|
||||||
|
* use a more efficient match finding algorithm. However, this produces different
|
||||||
|
* results than when the two buffers are non-contiguous. This flag forces zstd
|
||||||
|
* to always load the prefix in non-contiguous mode, even if it happens to be
|
||||||
|
* adjacent to the data, to guarantee determinism.
|
||||||
|
*
|
||||||
|
* If you really care about determinism when using a dictionary or prefix,
|
||||||
|
* like when doing delta compression, you should select this option. It comes
|
||||||
|
* at a speed penalty of about ~2.5% if the dictionary and data happened to be
|
||||||
|
* contiguous, and is free if they weren't contiguous. We don't expect that
|
||||||
|
* intentionally making the dictionary and data contiguous will be worth the
|
||||||
|
* cost to memcpy() the data.
|
||||||
|
*/
|
||||||
|
#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15
|
||||||
|
|
||||||
/*! ZSTD_CCtx_getParameter() :
|
/*! ZSTD_CCtx_getParameter() :
|
||||||
* Get the requested compression parameter value, selected by enum ZSTD_cParameter,
|
* Get the requested compression parameter value, selected by enum ZSTD_cParameter,
|
||||||
* and store it into int* value.
|
* and store it into int* value.
|
||||||
* @return : 0, or an error code (which can be tested with ZSTD_isError()).
|
* @return : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
|
ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
|
||||||
|
|
||||||
|
|
||||||
/*! ZSTD_CCtx_params :
|
/*! ZSTD_CCtx_params :
|
||||||
|
@ -1817,13 +1926,13 @@ ZSTDLIB_API size_t ZSTD_CCtx_getParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param
|
||||||
* These parameters will be applied to
|
* These parameters will be applied to
|
||||||
* all subsequent frames.
|
* all subsequent frames.
|
||||||
* - ZSTD_compressStream2() : Do compression using the CCtx.
|
* - ZSTD_compressStream2() : Do compression using the CCtx.
|
||||||
* - ZSTD_freeCCtxParams() : Free the memory.
|
* - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer.
|
||||||
*
|
*
|
||||||
* This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
|
* This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
|
||||||
* for static allocation of CCtx for single-threaded compression.
|
* for static allocation of CCtx for single-threaded compression.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
|
ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
|
||||||
ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);
|
ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */
|
||||||
|
|
||||||
/*! ZSTD_CCtxParams_reset() :
|
/*! ZSTD_CCtxParams_reset() :
|
||||||
* Reset params to default values.
|
* Reset params to default values.
|
||||||
|
@ -1842,7 +1951,7 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compre
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
|
ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
|
||||||
|
|
||||||
/*! ZSTD_CCtxParams_setParameter() :
|
/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+
|
||||||
* Similar to ZSTD_CCtx_setParameter.
|
* Similar to ZSTD_CCtx_setParameter.
|
||||||
* Set one compression parameter, selected by enum ZSTD_cParameter.
|
* Set one compression parameter, selected by enum ZSTD_cParameter.
|
||||||
* Parameters must be applied to a ZSTD_CCtx using
|
* Parameters must be applied to a ZSTD_CCtx using
|
||||||
|
@ -1857,7 +1966,7 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_c
|
||||||
* Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
|
* Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
|
||||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
|
||||||
|
|
||||||
/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
|
/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
|
||||||
* Apply a set of ZSTD_CCtx_params to the compression context.
|
* Apply a set of ZSTD_CCtx_params to the compression context.
|
||||||
|
@ -1983,12 +2092,38 @@ ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param
|
||||||
*/
|
*/
|
||||||
#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3
|
#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3
|
||||||
|
|
||||||
|
/* ZSTD_d_refMultipleDDicts
|
||||||
|
* Experimental parameter.
|
||||||
|
* Default is 0 == disabled. Set to 1 to enable
|
||||||
|
*
|
||||||
|
* If enabled and dctx is allocated on the heap, then additional memory will be allocated
|
||||||
|
* to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict()
|
||||||
|
* using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead
|
||||||
|
* store all references. At decompression time, the appropriate dictID is selected
|
||||||
|
* from the set of DDicts based on the dictID in the frame.
|
||||||
|
*
|
||||||
|
* Usage is simply calling ZSTD_refDDict() on multiple dict buffers.
|
||||||
|
*
|
||||||
|
* Param has values of byte ZSTD_refMultipleDDicts_e
|
||||||
|
*
|
||||||
|
* WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory
|
||||||
|
* allocation for the hash table. ZSTD_freeDCtx() also frees this memory.
|
||||||
|
* Memory is allocated as per ZSTD_DCtx::customMem.
|
||||||
|
*
|
||||||
|
* Although this function allocates memory for the table, the user is still responsible for
|
||||||
|
* memory management of the underlying ZSTD_DDict* themselves.
|
||||||
|
*/
|
||||||
|
#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4
|
||||||
|
|
||||||
|
|
||||||
/*! ZSTD_DCtx_setFormat() :
|
/*! ZSTD_DCtx_setFormat() :
|
||||||
|
* This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().
|
||||||
* Instruct the decoder context about what kind of data to decode next.
|
* Instruct the decoder context about what kind of data to decode next.
|
||||||
* This instruction is mandatory to decode data without a fully-formed header,
|
* This instruction is mandatory to decode data without a fully-formed header,
|
||||||
* such ZSTD_f_zstd1_magicless for example.
|
* such ZSTD_f_zstd1_magicless for example.
|
||||||
* @return : 0, or an error code (which can be tested using ZSTD_isError()). */
|
* @return : 0, or an error code (which can be tested using ZSTD_isError()). */
|
||||||
ZSTDLIB_API size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
|
ZSTD_DEPRECATED("use ZSTD_DCtx_setParameter() instead")
|
||||||
|
size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
|
||||||
|
|
||||||
/*! ZSTD_decompressStream_simpleArgs() :
|
/*! ZSTD_decompressStream_simpleArgs() :
|
||||||
* Same as ZSTD_decompressStream(),
|
* Same as ZSTD_decompressStream(),
|
||||||
|
@ -2012,7 +2147,7 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
|
||||||
/*===== Advanced Streaming compression functions =====*/
|
/*===== Advanced Streaming compression functions =====*/
|
||||||
|
|
||||||
/*! ZSTD_initCStream_srcSize() :
|
/*! ZSTD_initCStream_srcSize() :
|
||||||
* This function is deprecated, and equivalent to:
|
* This function is DEPRECATED, and equivalent to:
|
||||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||||
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
|
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
|
||||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||||
|
@ -2021,15 +2156,15 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
|
||||||
* pledgedSrcSize must be correct. If it is not known at init time, use
|
* pledgedSrcSize must be correct. If it is not known at init time, use
|
||||||
* ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
|
* ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
|
||||||
* "0" also disables frame content size field. It may be enabled in the future.
|
* "0" also disables frame content size field. It may be enabled in the future.
|
||||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
* This prototype will generate compilation warnings.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t
|
ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
|
||||||
ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
|
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
|
||||||
int compressionLevel,
|
int compressionLevel,
|
||||||
unsigned long long pledgedSrcSize);
|
unsigned long long pledgedSrcSize);
|
||||||
|
|
||||||
/*! ZSTD_initCStream_usingDict() :
|
/*! ZSTD_initCStream_usingDict() :
|
||||||
* This function is deprecated, and is equivalent to:
|
* This function is DEPRECATED, and is equivalent to:
|
||||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||||
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
|
* ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
|
||||||
|
@ -2038,15 +2173,15 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
|
||||||
* dict == NULL or dictSize < 8, in which case no dict is used.
|
* dict == NULL or dictSize < 8, in which case no dict is used.
|
||||||
* Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if
|
* Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if
|
||||||
* it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
|
* it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
|
||||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
* This prototype will generate compilation warnings.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t
|
ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
|
||||||
ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
|
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
|
||||||
const void* dict, size_t dictSize,
|
const void* dict, size_t dictSize,
|
||||||
int compressionLevel);
|
int compressionLevel);
|
||||||
|
|
||||||
/*! ZSTD_initCStream_advanced() :
|
/*! ZSTD_initCStream_advanced() :
|
||||||
* This function is deprecated, and is approximately equivalent to:
|
* This function is DEPRECATED, and is approximately equivalent to:
|
||||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||||
* // Pseudocode: Set each zstd parameter and leave the rest as-is.
|
* // Pseudocode: Set each zstd parameter and leave the rest as-is.
|
||||||
* for ((param, value) : params) {
|
* for ((param, value) : params) {
|
||||||
|
@ -2058,23 +2193,24 @@ ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
|
||||||
* dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.
|
* dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.
|
||||||
* pledgedSrcSize must be correct.
|
* pledgedSrcSize must be correct.
|
||||||
* If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
|
* If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
|
||||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
* This prototype will generate compilation warnings.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t
|
ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
|
||||||
ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
||||||
const void* dict, size_t dictSize,
|
const void* dict, size_t dictSize,
|
||||||
ZSTD_parameters params,
|
ZSTD_parameters params,
|
||||||
unsigned long long pledgedSrcSize);
|
unsigned long long pledgedSrcSize);
|
||||||
|
|
||||||
/*! ZSTD_initCStream_usingCDict() :
|
/*! ZSTD_initCStream_usingCDict() :
|
||||||
* This function is deprecated, and equivalent to:
|
* This function is DEPRECATED, and equivalent to:
|
||||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||||
* ZSTD_CCtx_refCDict(zcs, cdict);
|
* ZSTD_CCtx_refCDict(zcs, cdict);
|
||||||
*
|
*
|
||||||
* note : cdict will just be referenced, and must outlive compression session
|
* note : cdict will just be referenced, and must outlive compression session
|
||||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
* This prototype will generate compilation warnings.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
|
ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions")
|
||||||
|
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
|
||||||
|
|
||||||
/*! ZSTD_initCStream_usingCDict_advanced() :
|
/*! ZSTD_initCStream_usingCDict_advanced() :
|
||||||
* This function is DEPRECATED, and is approximately equivalent to:
|
* This function is DEPRECATED, and is approximately equivalent to:
|
||||||
|
@ -2089,18 +2225,21 @@ ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDi
|
||||||
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
|
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
|
||||||
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
|
* pledgedSrcSize must be correct. If srcSize is not known at init time, use
|
||||||
* value ZSTD_CONTENTSIZE_UNKNOWN.
|
* value ZSTD_CONTENTSIZE_UNKNOWN.
|
||||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
* This prototype will generate compilation warnings.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t
|
ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions")
|
||||||
ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
||||||
const ZSTD_CDict* cdict,
|
const ZSTD_CDict* cdict,
|
||||||
ZSTD_frameParameters fParams,
|
ZSTD_frameParameters fParams,
|
||||||
unsigned long long pledgedSrcSize);
|
unsigned long long pledgedSrcSize);
|
||||||
|
|
||||||
/*! ZSTD_resetCStream() :
|
/*! ZSTD_resetCStream() :
|
||||||
* This function is deprecated, and is equivalent to:
|
* This function is DEPRECATED, and is equivalent to:
|
||||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||||
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
* ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
|
||||||
|
* Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but
|
||||||
|
* ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be
|
||||||
|
* explicitly specified.
|
||||||
*
|
*
|
||||||
* start a new frame, using same parameters from previous frame.
|
* start a new frame, using same parameters from previous frame.
|
||||||
* This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
|
* This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
|
||||||
|
@ -2110,9 +2249,10 @@ ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
||||||
* For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs,
|
* For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs,
|
||||||
* but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.
|
* but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.
|
||||||
* @return : 0, or an error code (which can be tested using ZSTD_isError())
|
* @return : 0, or an error code (which can be tested using ZSTD_isError())
|
||||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
* This prototype will generate compilation warnings.
|
||||||
*/
|
*/
|
||||||
ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
|
||||||
|
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -2199,8 +2339,7 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||||
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
|
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
|
||||||
|
|
||||||
Start by initializing a context.
|
Start by initializing a context.
|
||||||
Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression,
|
Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.
|
||||||
or ZSTD_compressBegin_advanced(), for finer parameter control.
|
|
||||||
It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx()
|
It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx()
|
||||||
|
|
||||||
Then, consume your input using ZSTD_compressContinue().
|
Then, consume your input using ZSTD_compressContinue().
|
||||||
|
@ -2225,15 +2364,17 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||||
/*===== Buffer-less streaming compression functions =====*/
|
/*===== Buffer-less streaming compression functions =====*/
|
||||||
ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
|
ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
|
||||||
ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
||||||
ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */
|
|
||||||
ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
|
ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
|
||||||
ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
|
|
||||||
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
|
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
|
||||||
|
|
||||||
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||||
ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||||
|
|
||||||
|
/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */
|
||||||
|
ZSTD_DEPRECATED("use advanced API to access custom parameters")
|
||||||
|
size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */
|
||||||
|
ZSTD_DEPRECATED("use advanced API to access custom parameters")
|
||||||
|
size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
|
||||||
/**
|
/**
|
||||||
Buffer-less streaming decompression (synchronous mode)
|
Buffer-less streaming decompression (synchronous mode)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.
|
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This source code is licensed under both the BSD-style license (found in the
|
* This source code is licensed under both the BSD-style license (found in the
|
Loading…
Reference in New Issue