initial commit
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
# ################################################################
|
||||
# Copyright (c) Yann Collet, Facebook, Inc.
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -161,6 +161,13 @@ The file structure is designed to make this selection manually achievable for an
|
||||
`ZSTD_DCtx` decompression contexts,
|
||||
but might also result in a small decompression speed cost.
|
||||
|
||||
- The C compiler macros `ZSTDLIB_VISIBLE`, `ZSTDERRORLIB_VISIBLE` and `ZDICTLIB_VISIBLE`
|
||||
can be overridden to control the visibility of zstd's API. Additionally,
|
||||
`ZSTDLIB_STATIC_API` and `ZDICTLIB_STATIC_API` can be overridden to control the visibility
|
||||
of zstd's static API. Specifically, it can be set to `ZSTDLIB_HIDDEN` to hide the symbols
|
||||
from the shared library. These macros default to `ZSTDLIB_VISIBILITY`,
|
||||
`ZSTDERRORLIB_VSIBILITY`, and `ZDICTLIB_VISIBILITY` if unset, for backwards compatibility
|
||||
with the old macro names.
|
||||
|
||||
#### Windows : using MinGW+MSYS to create DLL
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* bitstream
|
||||
* Part of FSE library
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
|
||||
+14
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -281,7 +281,18 @@
|
||||
* Sanitizer
|
||||
*****************************************************************/
|
||||
|
||||
#if ZSTD_MEMORY_SANITIZER
|
||||
/* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an
|
||||
* abundance of caution, disable our custom poisoning on mingw. */
|
||||
#ifdef __MINGW32__
|
||||
#ifndef ZSTD_ASAN_DONT_POISON_WORKSPACE
|
||||
#define ZSTD_ASAN_DONT_POISON_WORKSPACE 1
|
||||
#endif
|
||||
#ifndef ZSTD_MSAN_DONT_POISON_WORKSPACE
|
||||
#define ZSTD_MSAN_DONT_POISON_WORKSPACE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
||||
/* Not all platforms that support msan provide sanitizers/msan_interface.h.
|
||||
* We therefore declare the functions we need ourselves, rather than trying to
|
||||
* include the header file... */
|
||||
@@ -302,7 +313,7 @@ void __msan_poison(const volatile void *a, size_t size);
|
||||
intptr_t __msan_test_shadow(const volatile void *x, size_t size);
|
||||
#endif
|
||||
|
||||
#if ZSTD_ADDRESS_SANITIZER
|
||||
#if ZSTD_ADDRESS_SANITIZER && !defined(ZSTD_ASAN_DONT_POISON_WORKSPACE)
|
||||
/* Not all platforms that support asan provide sanitizers/asan_interface.h.
|
||||
* We therefore declare the functions we need ourselves, rather than trying to
|
||||
* include the header file... */
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* debug
|
||||
* Part of FSE library
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* debug
|
||||
* Part of FSE library
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* ******************************************************************
|
||||
* Common functions of New Generation Entropy library
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "error_private.h" /* ERR_*, ERROR */
|
||||
#define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */
|
||||
#include "fse.h"
|
||||
#define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */
|
||||
#include "huf.h"
|
||||
#include "bits.h" /* ZSDT_highbit32, ZSTD_countTrailingZeros32 */
|
||||
|
||||
@@ -237,7 +236,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
|
||||
return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0);
|
||||
return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* flags */ 0);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
@@ -329,13 +328,13 @@ size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||
const void* src, size_t srcSize,
|
||||
void* workSpace, size_t wkspSize,
|
||||
int bmi2)
|
||||
int flags)
|
||||
{
|
||||
#if DYNAMIC_BMI2
|
||||
if (bmi2) {
|
||||
if (flags & HUF_flags_bmi2) {
|
||||
return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
|
||||
}
|
||||
#endif
|
||||
(void)bmi2;
|
||||
(void)flags;
|
||||
return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -29,7 +29,9 @@ const char* ERR_getErrorString(ERR_enum code)
|
||||
case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding";
|
||||
case PREFIX(corruption_detected): return "Data corruption detected";
|
||||
case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
|
||||
case PREFIX(literals_headerWrong): return "Header of Literals' block doesn't respect format specification";
|
||||
case PREFIX(parameter_unsupported): return "Unsupported parameter";
|
||||
case PREFIX(parameter_combination_unsupported): return "Unsupported combination of parameters";
|
||||
case PREFIX(parameter_outOfBound): return "Parameter is out of bound";
|
||||
case PREFIX(init_missing): return "Context should be init first";
|
||||
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
|
||||
@@ -45,11 +47,15 @@ const char* ERR_getErrorString(ERR_enum code)
|
||||
case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
|
||||
case PREFIX(srcSize_wrong): return "Src size is incorrect";
|
||||
case PREFIX(dstBuffer_null): return "Operation on NULL destination buffer";
|
||||
case PREFIX(noForwardProgress_destFull): return "Operation made no progress over multiple calls, due to output buffer being full";
|
||||
case PREFIX(noForwardProgress_inputEmpty): return "Operation made no progress over multiple calls, due to input being empty";
|
||||
/* following error codes are not stable and may be removed or changed in a future version */
|
||||
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
|
||||
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
|
||||
case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
|
||||
case PREFIX(srcBuffer_wrong): return "Source buffer is wrong";
|
||||
case PREFIX(externalMatchFinder_failed): return "External matchfinder returned an error code";
|
||||
case PREFIX(externalSequences_invalid): return "External sequences are not valid";
|
||||
case PREFIX(maxCode):
|
||||
default: return notErrorCode;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+3
-81
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* FSE : Finite State Entropy codec
|
||||
* Public Prototypes declaration
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
@@ -53,34 +53,6 @@ extern "C" {
|
||||
FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
|
||||
|
||||
|
||||
/*-****************************************
|
||||
* FSE simple functions
|
||||
******************************************/
|
||||
/*! FSE_compress() :
|
||||
Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
|
||||
'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize).
|
||||
@return : size of compressed data (<= dstCapacity).
|
||||
Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
||||
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.
|
||||
if FSE_isError(return), compression failed (more details using FSE_getErrorName())
|
||||
*/
|
||||
FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/*! FSE_decompress():
|
||||
Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
|
||||
into already allocated destination buffer 'dst', of size 'dstCapacity'.
|
||||
@return : size of regenerated data (<= maxDstSize),
|
||||
or an error code, which can be tested using FSE_isError() .
|
||||
|
||||
** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!!
|
||||
Why ? : making this distinction requires a header.
|
||||
Header management is intentionally delegated to the user layer, which can better manage special cases.
|
||||
*/
|
||||
FSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity,
|
||||
const void* cSrc, size_t cSrcSize);
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* Tool functions
|
||||
******************************************/
|
||||
@@ -91,20 +63,6 @@ FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return
|
||||
FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* FSE advanced functions
|
||||
******************************************/
|
||||
/*! FSE_compress2() :
|
||||
Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'
|
||||
Both parameters can be defined as '0' to mean : use default value
|
||||
@return : size of compressed data
|
||||
Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!
|
||||
if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
|
||||
if FSE_isError(return), it's an error code.
|
||||
*/
|
||||
FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
|
||||
/*-*****************************************
|
||||
* FSE detailed API
|
||||
******************************************/
|
||||
@@ -164,8 +122,6 @@ FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,
|
||||
/*! Constructor and Destructor of FSE_CTable.
|
||||
Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
|
||||
typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
|
||||
FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog);
|
||||
FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct);
|
||||
|
||||
/*! FSE_buildCTable():
|
||||
Builds `ct`, which must be already allocated, using FSE_createCTable().
|
||||
@@ -241,23 +197,7 @@ FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,
|
||||
unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
|
||||
const void* rBuffer, size_t rBuffSize, int bmi2);
|
||||
|
||||
/*! Constructor and Destructor of FSE_DTable.
|
||||
Note that its size depends on 'tableLog' */
|
||||
typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
|
||||
FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog);
|
||||
FSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt);
|
||||
|
||||
/*! FSE_buildDTable():
|
||||
Builds 'dt', which must be already allocated, using FSE_createDTable().
|
||||
return : 0, or an errorCode, which can be tested using FSE_isError() */
|
||||
FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
/*! FSE_decompress_usingDTable():
|
||||
Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
|
||||
into `dst` which must be already allocated.
|
||||
@return : size of regenerated data (necessarily <= `dstCapacity`),
|
||||
or an errorCode, which can be tested using FSE_isError() */
|
||||
FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);
|
||||
|
||||
/*!
|
||||
Tutorial :
|
||||
@@ -320,16 +260,6 @@ If there is an error, the function will return an error code, which can be teste
|
||||
unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
|
||||
/**< same as FSE_optimalTableLog(), which used `minus==2` */
|
||||
|
||||
/* FSE_compress_wksp() :
|
||||
* Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
|
||||
* FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
|
||||
*/
|
||||
#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
|
||||
size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
|
||||
|
||||
size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
|
||||
/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
|
||||
|
||||
size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
|
||||
/**< build a fake FSE_CTable, designed to compress always the same symbolValue */
|
||||
|
||||
@@ -347,19 +277,11 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsi
|
||||
FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
|
||||
/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */
|
||||
|
||||
size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
|
||||
/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
|
||||
|
||||
size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char 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) + 1 + 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))
|
||||
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)` */
|
||||
|
||||
size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);
|
||||
/**< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */
|
||||
/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)`.
|
||||
* Set bmi2 to 1 if your CPU supports BMI2 or 0 if it doesn't */
|
||||
|
||||
typedef enum {
|
||||
FSE_repeat_none, /**< Cannot use the previous table */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* ******************************************************************
|
||||
* FSE : Finite State Entropy decoder
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
@@ -56,19 +56,6 @@
|
||||
#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
|
||||
#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
|
||||
|
||||
|
||||
/* Function templates */
|
||||
FSE_DTable* FSE_createDTable (unsigned tableLog)
|
||||
{
|
||||
if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
|
||||
return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
|
||||
}
|
||||
|
||||
void FSE_freeDTable (FSE_DTable* dt)
|
||||
{
|
||||
ZSTD_free(dt);
|
||||
}
|
||||
|
||||
static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
|
||||
{
|
||||
void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
|
||||
@@ -185,49 +172,6 @@ size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsi
|
||||
/*-*******************************************************
|
||||
* Decompression (Byte symbols)
|
||||
*********************************************************/
|
||||
size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
|
||||
{
|
||||
void* ptr = dt;
|
||||
FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
|
||||
void* dPtr = dt + 1;
|
||||
FSE_decode_t* const cell = (FSE_decode_t*)dPtr;
|
||||
|
||||
DTableH->tableLog = 0;
|
||||
DTableH->fastMode = 0;
|
||||
|
||||
cell->newState = 0;
|
||||
cell->symbol = symbolValue;
|
||||
cell->nbBits = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
|
||||
{
|
||||
void* ptr = dt;
|
||||
FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
|
||||
void* dPtr = dt + 1;
|
||||
FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;
|
||||
const unsigned tableSize = 1 << nbBits;
|
||||
const unsigned tableMask = tableSize - 1;
|
||||
const unsigned maxSV1 = tableMask+1;
|
||||
unsigned s;
|
||||
|
||||
/* Sanity checks */
|
||||
if (nbBits < 1) return ERROR(GENERIC); /* min size */
|
||||
|
||||
/* Build Decoding Table */
|
||||
DTableH->tableLog = (U16)nbBits;
|
||||
DTableH->fastMode = 1;
|
||||
for (s=0; s<maxSV1; s++) {
|
||||
dinfo[s].newState = 0;
|
||||
dinfo[s].symbol = (BYTE)s;
|
||||
dinfo[s].nbBits = (BYTE)nbBits;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(
|
||||
void* dst, size_t maxDstSize,
|
||||
@@ -291,26 +235,6 @@ FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
|
||||
size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const FSE_DTable* dt)
|
||||
{
|
||||
const void* ptr = dt;
|
||||
const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
|
||||
const U32 fastMode = DTableH->fastMode;
|
||||
|
||||
/* select fast mode (static) */
|
||||
if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
|
||||
return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
|
||||
}
|
||||
|
||||
|
||||
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
|
||||
{
|
||||
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 */
|
||||
@@ -384,22 +308,4 @@ size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc,
|
||||
return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
|
||||
}
|
||||
|
||||
|
||||
typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
|
||||
|
||||
#ifndef ZSTD_NO_UNUSED_FUNCTIONS
|
||||
size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) {
|
||||
U32 wksp[FSE_BUILD_DTABLE_WKSP_SIZE_U32(FSE_TABLELOG_ABSOLUTE_MAX, FSE_MAX_SYMBOL_VALUE)];
|
||||
return FSE_buildDTable_wksp(dt, normalizedCounter, maxSymbolValue, tableLog, wksp, sizeof(wksp));
|
||||
}
|
||||
|
||||
size_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
/* Static analyzer seems unable to understand this table will be properly initialized later */
|
||||
U32 wksp[FSE_DECOMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)];
|
||||
return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, FSE_MAX_TABLELOG, wksp, sizeof(wksp));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* FSE_COMMONDEFS_ONLY */
|
||||
|
||||
+66
-168
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* huff0 huffman codec,
|
||||
* part of Finite State Entropy library
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
@@ -21,100 +21,23 @@ extern "C" {
|
||||
|
||||
/* *** Dependencies *** */
|
||||
#include "zstd_deps.h" /* size_t */
|
||||
|
||||
|
||||
/* *** library symbols visibility *** */
|
||||
/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual,
|
||||
* HUF symbols remain "private" (internal symbols for library only).
|
||||
* Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */
|
||||
#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define HUF_PUBLIC_API __attribute__ ((visibility ("default")))
|
||||
#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
|
||||
# define HUF_PUBLIC_API __declspec(dllexport)
|
||||
#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
|
||||
# define HUF_PUBLIC_API __declspec(dllimport) /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */
|
||||
#else
|
||||
# define HUF_PUBLIC_API
|
||||
#endif
|
||||
|
||||
|
||||
/* ========================== */
|
||||
/* *** simple functions *** */
|
||||
/* ========================== */
|
||||
|
||||
/** HUF_compress() :
|
||||
* Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.
|
||||
* 'dst' buffer must be already allocated.
|
||||
* Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize).
|
||||
* `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB.
|
||||
* @return : size of compressed data (<= `dstCapacity`).
|
||||
* Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
|
||||
* if HUF_isError(return), compression failed (more details using HUF_getErrorName())
|
||||
*/
|
||||
HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
/** HUF_decompress() :
|
||||
* Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
|
||||
* into already allocated buffer 'dst', of minimum size 'dstSize'.
|
||||
* `originalSize` : **must** be the ***exact*** size of original (uncompressed) data.
|
||||
* Note : in contrast with FSE, HUF_decompress can regenerate
|
||||
* RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
|
||||
* because it knows size to regenerate (originalSize).
|
||||
* @return : size of regenerated data (== originalSize),
|
||||
* or an error code, which can be tested using HUF_isError()
|
||||
*/
|
||||
HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize,
|
||||
const void* cSrc, size_t cSrcSize);
|
||||
|
||||
|
||||
/* *** Tool functions *** */
|
||||
#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
|
||||
HUF_PUBLIC_API size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
|
||||
|
||||
/* Error Management */
|
||||
HUF_PUBLIC_API unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
|
||||
HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */
|
||||
|
||||
|
||||
/* *** Advanced function *** */
|
||||
|
||||
/** HUF_compress2() :
|
||||
* Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`.
|
||||
* `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX .
|
||||
* `tableLog` must be `<= HUF_TABLELOG_MAX` . */
|
||||
HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned tableLog);
|
||||
|
||||
/** HUF_compress4X_wksp() :
|
||||
* Same as HUF_compress2(), but uses externally allocated `workSpace`.
|
||||
* `workspace` must be at least as large as HUF_WORKSPACE_SIZE */
|
||||
#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */)
|
||||
#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64))
|
||||
HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned tableLog,
|
||||
void* workSpace, size_t wkspSize);
|
||||
|
||||
#endif /* HUF_H_298734234 */
|
||||
|
||||
/* ******************************************************************
|
||||
* WARNING !!
|
||||
* The following section contains advanced and experimental definitions
|
||||
* which shall never be used in the context of a dynamic library,
|
||||
* because they are not guaranteed to remain stable in the future.
|
||||
* Only consider them in association with static linking.
|
||||
* *****************************************************************/
|
||||
#if defined(HUF_STATIC_LINKING_ONLY) && !defined(HUF_H_HUF_STATIC_LINKING_ONLY)
|
||||
#define HUF_H_HUF_STATIC_LINKING_ONLY
|
||||
|
||||
/* *** Dependencies *** */
|
||||
#include "mem.h" /* U32 */
|
||||
#include "mem.h" /* U32 */
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "fse.h"
|
||||
|
||||
|
||||
/* *** Tool functions *** */
|
||||
#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
|
||||
size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
|
||||
|
||||
/* Error Management */
|
||||
unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
|
||||
const char* HUF_getErrorName(size_t code); /**< provides error code string (useful for debugging) */
|
||||
|
||||
|
||||
#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */)
|
||||
#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64))
|
||||
|
||||
/* *** Constants *** */
|
||||
#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_TABLELOG_ABSOLUTEMAX */
|
||||
#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */
|
||||
@@ -154,30 +77,49 @@ typedef U32 HUF_DTable;
|
||||
/* ****************************************
|
||||
* Advanced decompression functions
|
||||
******************************************/
|
||||
size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||
#endif
|
||||
|
||||
size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< decodes RLE and uncompressed */
|
||||
size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */
|
||||
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */
|
||||
size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||
size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||
size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
|
||||
#endif
|
||||
/**
|
||||
* Huffman flags bitset.
|
||||
* For all flags, 0 is the default value.
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* If compiled with DYNAMIC_BMI2: Set flag only if the CPU supports BMI2 at runtime.
|
||||
* Otherwise: Ignored.
|
||||
*/
|
||||
HUF_flags_bmi2 = (1 << 0),
|
||||
/**
|
||||
* If set: Test possible table depths to find the one that produces the smallest header + encoded size.
|
||||
* If unset: Use heuristic to find the table depth.
|
||||
*/
|
||||
HUF_flags_optimalDepth = (1 << 1),
|
||||
/**
|
||||
* If set: If the previous table can encode the input, always reuse the previous table.
|
||||
* If unset: If the previous table can encode the input, reuse the previous table if it results in a smaller output.
|
||||
*/
|
||||
HUF_flags_preferRepeat = (1 << 2),
|
||||
/**
|
||||
* If set: Sample the input and check if the sample is uncompressible, if it is then don't attempt to compress.
|
||||
* If unset: Always histogram the entire input.
|
||||
*/
|
||||
HUF_flags_suspectUncompressible = (1 << 3),
|
||||
/**
|
||||
* If set: Don't use assembly implementations
|
||||
* If unset: Allow using assembly implementations
|
||||
*/
|
||||
HUF_flags_disableAsm = (1 << 4),
|
||||
/**
|
||||
* If set: Don't use the fast decoding loop, always use the fallback decoding loop.
|
||||
* If unset: Use the fast decoding loop when possible.
|
||||
*/
|
||||
HUF_flags_disableFast = (1 << 5)
|
||||
} HUF_flags_e;
|
||||
|
||||
|
||||
/* ****************************************
|
||||
* HUF detailed API
|
||||
* ****************************************/
|
||||
#define HUF_OPTIMAL_DEPTH_THRESHOLD ZSTD_btultra
|
||||
typedef enum {
|
||||
HUF_depth_fast, /** Use heuristic to find the table depth**/
|
||||
HUF_depth_optimal /** Test possible table depths to find the one that produces the smallest header + encoded size**/
|
||||
} HUF_depth_mode;
|
||||
|
||||
/*! HUF_compress() does the following:
|
||||
* 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h")
|
||||
@@ -193,12 +135,9 @@ typedef enum {
|
||||
unsigned HUF_minTableLog(unsigned symbolCardinality);
|
||||
unsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue);
|
||||
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, void* workSpace,
|
||||
size_t wkspSize, HUF_CElt* table, const unsigned* count, HUF_depth_mode depthMode); /* table is used as scratch space for building and testing tables, not a return value */
|
||||
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 wkspSize, HUF_CElt* table, const unsigned* count, int flags); /* table is used as scratch space for building and testing tables, not a return value */
|
||||
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_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
|
||||
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags);
|
||||
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);
|
||||
|
||||
@@ -218,14 +157,13 @@ size_t HUF_compress4X_repeat(void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned tableLog,
|
||||
void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2,
|
||||
unsigned suspectUncompressible, HUF_depth_mode depthMode);
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int flags);
|
||||
|
||||
/** HUF_buildCTable_wksp() :
|
||||
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
|
||||
* `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.
|
||||
*/
|
||||
#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1)
|
||||
#define HUF_CTABLE_WORKSPACE_SIZE_U32 ((4 * (HUF_SYMBOLVALUE_MAX + 1)) + 192)
|
||||
#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))
|
||||
size_t HUF_buildCTable_wksp (HUF_CElt* tree,
|
||||
const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,
|
||||
@@ -251,7 +189,7 @@ size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,
|
||||
U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
|
||||
const void* src, size_t srcSize,
|
||||
void* workspace, size_t wkspSize,
|
||||
int bmi2);
|
||||
int flags);
|
||||
|
||||
/** HUF_readCTable() :
|
||||
* Loading a CTable saved with HUF_writeCTable() */
|
||||
@@ -289,32 +227,12 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
|
||||
#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))
|
||||
#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
|
||||
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize);
|
||||
size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
|
||||
#endif
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize);
|
||||
size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
|
||||
#endif
|
||||
|
||||
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||
#endif
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||
#endif
|
||||
|
||||
|
||||
/* ====================== */
|
||||
/* single stream variants */
|
||||
/* ====================== */
|
||||
|
||||
size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
|
||||
size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U64 U64 */
|
||||
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
|
||||
size_t HUF_compress1X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
|
||||
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags);
|
||||
/** HUF_compress1X_repeat() :
|
||||
* Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
|
||||
* If it uses hufTable it does not modify hufTable or repeat.
|
||||
@@ -325,50 +243,30 @@ size_t HUF_compress1X_repeat(void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned tableLog,
|
||||
void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2,
|
||||
unsigned suspectUncompressible, HUF_depth_mode depthMode);
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int flags);
|
||||
|
||||
size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
|
||||
size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
|
||||
#endif
|
||||
|
||||
size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
|
||||
size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< single-symbol decoder */
|
||||
size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< single-symbol decoder */
|
||||
#endif
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< double-symbols decoder */
|
||||
size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< double-symbols decoder */
|
||||
#endif
|
||||
|
||||
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||
#endif
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
|
||||
size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags); /**< double-symbols decoder */
|
||||
#endif
|
||||
|
||||
/* BMI2 variants.
|
||||
* If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
|
||||
*/
|
||||
size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
|
||||
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags);
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||
size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);
|
||||
#endif
|
||||
size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
|
||||
size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags);
|
||||
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||
size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);
|
||||
#endif
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
|
||||
size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);
|
||||
#endif
|
||||
|
||||
#endif /* HUF_STATIC_LINKING_ONLY */
|
||||
#endif /* HUF_H_298734234 */
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
||||
+17
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -133,21 +133,15 @@ MEM_STATIC size_t MEM_swapST(size_t in);
|
||||
/*-**************************************************************
|
||||
* Memory I/O Implementation
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS :
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (i.e., not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
/* MEM_FORCE_MEMORY_ACCESS : For accessing unaligned memory:
|
||||
* Method 0 : always use `memcpy()`. Safe and portable.
|
||||
* Method 1 : Use compiler extension to set unaligned access.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets depending on alignment.
|
||||
* In some circumstances, it's the only known way to get the most performance (i.e. GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
* Default : method 1 if supported, else method 0
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# ifdef __GNUC__
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -190,30 +184,19 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
#if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))
|
||||
__pragma( pack(push, 1) )
|
||||
typedef struct { U16 v; } unalign16;
|
||||
typedef struct { U32 v; } unalign32;
|
||||
typedef struct { U64 v; } unalign64;
|
||||
typedef struct { size_t v; } unalignArch;
|
||||
__pragma( pack(pop) )
|
||||
#else
|
||||
typedef struct { U16 v; } __attribute__((packed)) unalign16;
|
||||
typedef struct { U32 v; } __attribute__((packed)) unalign32;
|
||||
typedef struct { U64 v; } __attribute__((packed)) unalign64;
|
||||
typedef struct { size_t v; } __attribute__((packed)) unalignArch;
|
||||
#endif
|
||||
typedef __attribute__((aligned(1))) U16 unalign16;
|
||||
typedef __attribute__((aligned(1))) U32 unalign32;
|
||||
typedef __attribute__((aligned(1))) U64 unalign64;
|
||||
typedef __attribute__((aligned(1))) size_t unalignArch;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign16*)ptr)->v; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign32*)ptr)->v; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign64*)ptr)->v; }
|
||||
MEM_STATIC size_t MEM_readST(const void* ptr) { return ((const unalignArch*)ptr)->v; }
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return *(const unalign16*)ptr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return *(const unalign32*)ptr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return *(const unalign64*)ptr; }
|
||||
MEM_STATIC size_t MEM_readST(const void* ptr) { return *(const unalignArch*)ptr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign16*)memPtr)->v = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign32*)memPtr)->v = value; }
|
||||
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = value; }
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(unalign16*)memPtr = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(unalign32*)memPtr = value; }
|
||||
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(unalign64*)memPtr = value; }
|
||||
|
||||
#else
|
||||
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -173,7 +173,7 @@ static void POOL_join(POOL_ctx* ctx) {
|
||||
/* Join all of the threads */
|
||||
{ size_t i;
|
||||
for (i = 0; i < ctx->threadCapacity; ++i) {
|
||||
ZSTD_pthread_join(ctx->threads[i], NULL); /* note : could fail */
|
||||
ZSTD_pthread_join(ctx->threads[i]); /* note : could fail */
|
||||
} }
|
||||
}
|
||||
|
||||
@@ -271,7 +271,9 @@ static int isQueueFull(POOL_ctx const* ctx) {
|
||||
static void
|
||||
POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
|
||||
{
|
||||
POOL_job const job = {function, opaque};
|
||||
POOL_job job;
|
||||
job.function = function;
|
||||
job.opaque = opaque;
|
||||
assert(ctx != NULL);
|
||||
if (ctx->shutdown) return;
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -137,12 +137,20 @@
|
||||
/*
|
||||
* For x86 ELF targets, add .note.gnu.property section for Intel CET in
|
||||
* assembly sources when CET is enabled.
|
||||
*
|
||||
* Additionally, any function that may be called indirectly must begin
|
||||
* with ZSTD_CET_ENDBRANCH.
|
||||
*/
|
||||
#if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__)) \
|
||||
&& defined(__has_include)
|
||||
# if __has_include(<cet.h>)
|
||||
# include <cet.h>
|
||||
# define ZSTD_CET_ENDBRANCH _CET_ENDBR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZSTD_CET_ENDBRANCH
|
||||
# define ZSTD_CET_ENDBRANCH
|
||||
#endif
|
||||
|
||||
#endif /* ZSTD_PORTABILITY_MACROS_H */
|
||||
|
||||
+67
-15
@@ -23,8 +23,7 @@ int g_ZSTD_threading_useless_symbol;
|
||||
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||
|
||||
/**
|
||||
* Windows minimalist Pthread Wrapper, based on :
|
||||
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
|
||||
* Windows minimalist Pthread Wrapper
|
||||
*/
|
||||
|
||||
|
||||
@@ -35,39 +34,92 @@ int g_ZSTD_threading_useless_symbol;
|
||||
|
||||
/* === Implementation === */
|
||||
|
||||
typedef struct {
|
||||
void* (*start_routine)(void*);
|
||||
void* arg;
|
||||
int initialized;
|
||||
ZSTD_pthread_cond_t initialized_cond;
|
||||
ZSTD_pthread_mutex_t initialized_mutex;
|
||||
} ZSTD_thread_params_t;
|
||||
|
||||
static unsigned __stdcall worker(void *arg)
|
||||
{
|
||||
ZSTD_pthread_t* const thread = (ZSTD_pthread_t*) arg;
|
||||
thread->arg = thread->start_routine(thread->arg);
|
||||
void* (*start_routine)(void*);
|
||||
void* thread_arg;
|
||||
|
||||
/* Inialized thread_arg and start_routine and signal main thread that we don't need it
|
||||
* to wait any longer.
|
||||
*/
|
||||
{
|
||||
ZSTD_thread_params_t* thread_param = (ZSTD_thread_params_t*)arg;
|
||||
thread_arg = thread_param->arg;
|
||||
start_routine = thread_param->start_routine;
|
||||
|
||||
/* Signal main thread that we are running and do not depend on its memory anymore */
|
||||
ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex);
|
||||
thread_param->initialized = 1;
|
||||
ZSTD_pthread_cond_signal(&thread_param->initialized_cond);
|
||||
ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex);
|
||||
}
|
||||
|
||||
start_routine(thread_arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
|
||||
void* (*start_routine) (void*), void* arg)
|
||||
{
|
||||
ZSTD_thread_params_t thread_param;
|
||||
(void)unused;
|
||||
thread->arg = arg;
|
||||
thread->start_routine = start_routine;
|
||||
thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);
|
||||
|
||||
if (!thread->handle)
|
||||
thread_param.start_routine = start_routine;
|
||||
thread_param.arg = arg;
|
||||
thread_param.initialized = 0;
|
||||
*thread = NULL;
|
||||
|
||||
/* Setup thread initialization synchronization */
|
||||
if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) {
|
||||
/* Should never happen on Windows */
|
||||
return -1;
|
||||
}
|
||||
if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) {
|
||||
/* Should never happen on Windows */
|
||||
ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Spawn thread */
|
||||
*thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL);
|
||||
if (!thread) {
|
||||
ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
|
||||
ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
|
||||
return errno;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait for thread to be initialized */
|
||||
ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex);
|
||||
while(!thread_param.initialized) {
|
||||
ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex);
|
||||
}
|
||||
ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex);
|
||||
ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
|
||||
ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr)
|
||||
int ZSTD_pthread_join(ZSTD_pthread_t thread)
|
||||
{
|
||||
DWORD result;
|
||||
|
||||
if (!thread.handle) return 0;
|
||||
if (!thread) return 0;
|
||||
|
||||
result = WaitForSingleObject(thread.handle, INFINITE);
|
||||
CloseHandle(thread.handle);
|
||||
result = WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
|
||||
switch (result) {
|
||||
case WAIT_OBJECT_0:
|
||||
if (value_ptr) *value_ptr = thread.arg;
|
||||
return 0;
|
||||
case WAIT_ABANDONED:
|
||||
return EINVAL;
|
||||
|
||||
+5
-10
@@ -23,8 +23,7 @@ extern "C" {
|
||||
#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
|
||||
|
||||
/**
|
||||
* Windows minimalist Pthread Wrapper, based on :
|
||||
* http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
|
||||
* Windows minimalist Pthread Wrapper
|
||||
*/
|
||||
#ifdef WINVER
|
||||
# undef WINVER
|
||||
@@ -62,16 +61,12 @@ extern "C" {
|
||||
#define ZSTD_pthread_cond_broadcast(a) WakeAllConditionVariable((a))
|
||||
|
||||
/* ZSTD_pthread_create() and ZSTD_pthread_join() */
|
||||
typedef struct {
|
||||
HANDLE handle;
|
||||
void* (*start_routine)(void*);
|
||||
void* arg;
|
||||
} ZSTD_pthread_t;
|
||||
typedef HANDLE ZSTD_pthread_t;
|
||||
|
||||
int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
|
||||
void* (*start_routine) (void*), void* arg);
|
||||
|
||||
int ZSTD_pthread_join(ZSTD_pthread_t thread, void** value_ptr);
|
||||
int ZSTD_pthread_join(ZSTD_pthread_t thread);
|
||||
|
||||
/**
|
||||
* add here more wrappers as required
|
||||
@@ -99,7 +94,7 @@ int ZSTD_pthread_join(ZSTD_pthread_t thread, void** value_ptr);
|
||||
|
||||
#define ZSTD_pthread_t pthread_t
|
||||
#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
|
||||
#define ZSTD_pthread_join(a, b) pthread_join((a),(b))
|
||||
#define ZSTD_pthread_join(a) pthread_join((a),NULL)
|
||||
|
||||
#else /* DEBUGLEVEL >= 1 */
|
||||
|
||||
@@ -124,7 +119,7 @@ int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);
|
||||
|
||||
#define ZSTD_pthread_t pthread_t
|
||||
#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))
|
||||
#define ZSTD_pthread_join(a, b) pthread_join((a),(b))
|
||||
#define ZSTD_pthread_join(a) pthread_join((a),NULL)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* xxHash - Fast Hash algorithm
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - xxHash homepage: http://www.xxhash.com
|
||||
* - xxHash homepage: https://cyan4973.github.io/xxHash/
|
||||
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* xxHash - Fast Hash algorithm
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - xxHash homepage: http://www.xxhash.com
|
||||
* - xxHash homepage: https://cyan4973.github.io/xxHash/
|
||||
* - xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -1314,7 +1314,7 @@ XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr,
|
||||
* care, as what works on one compiler/platform/optimization level may cause
|
||||
* another to read garbage data or even crash.
|
||||
*
|
||||
* See http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details.
|
||||
* See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details.
|
||||
*
|
||||
* Prefer these methods in priority order (0 > 3 > 1 > 2)
|
||||
*/
|
||||
@@ -1655,7 +1655,7 @@ static xxh_u32 XXH_read32(const void* ptr)
|
||||
|
||||
/*
|
||||
* Portable and safe solution. Generally efficient.
|
||||
* see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
|
||||
* see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
|
||||
*/
|
||||
static xxh_u32 XXH_read32(const void* memPtr)
|
||||
{
|
||||
@@ -2296,7 +2296,7 @@ static xxh_u64 XXH_read64(const void* ptr)
|
||||
|
||||
/*
|
||||
* Portable and safe solution. Generally efficient.
|
||||
* see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
|
||||
* see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
|
||||
*/
|
||||
static xxh_u64 XXH_read64(const void* memPtr)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "../zstd.h"
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "fse.h"
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "huf.h"
|
||||
#ifndef XXH_STATIC_LINKING_ONLY
|
||||
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||
@@ -94,6 +93,7 @@ typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
|
||||
|
||||
#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
|
||||
#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */) /* for a non-null block */
|
||||
#define MIN_LITERALS_FOR_4_STREAMS 6
|
||||
|
||||
typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e;
|
||||
|
||||
@@ -113,6 +113,8 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
|
||||
#define LLFSELog 9
|
||||
#define OffFSELog 8
|
||||
#define MaxFSELog MAX(MAX(MLFSELog, LLFSELog), OffFSELog)
|
||||
#define MaxMLBits 16
|
||||
#define MaxLLBits 16
|
||||
|
||||
#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */
|
||||
/* Each table cannot take more than #symbols * FSELog bits */
|
||||
@@ -340,12 +342,13 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore
|
||||
* `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
|
||||
*/
|
||||
typedef struct {
|
||||
size_t nbBlocks;
|
||||
size_t compressedSize;
|
||||
unsigned long long decompressedBound;
|
||||
} ZSTD_frameSizeInfo; /* decompress & legacy */
|
||||
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
|
||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
|
||||
int ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
|
||||
|
||||
/* custom memory allocation functions */
|
||||
void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+2
-120
@@ -1,6 +1,6 @@
|
||||
/* ******************************************************************
|
||||
* FSE : Finite State Entropy encoder
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
@@ -91,7 +91,7 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
|
||||
assert(tableLog < 16); /* required for threshold strategy to work */
|
||||
|
||||
/* For explanations on how to distribute symbol values over the table :
|
||||
* http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
|
||||
* https://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */
|
||||
|
||||
#ifdef __clang_analyzer__
|
||||
ZSTD_memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */
|
||||
@@ -343,16 +343,6 @@ size_t FSE_writeNCount (void* buffer, size_t bufferSize,
|
||||
* FSE Compression Code
|
||||
****************************************************************/
|
||||
|
||||
FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
size_t size;
|
||||
if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
|
||||
size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);
|
||||
return (FSE_CTable*)ZSTD_malloc(size);
|
||||
}
|
||||
|
||||
void FSE_freeCTable (FSE_CTable* ct) { ZSTD_free(ct); }
|
||||
|
||||
/* provides the minimum logSize to safely represent a distribution */
|
||||
static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)
|
||||
{
|
||||
@@ -533,40 +523,6 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,
|
||||
return tableLog;
|
||||
}
|
||||
|
||||
|
||||
/* fake FSE_CTable, for raw (uncompressed) input */
|
||||
size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits)
|
||||
{
|
||||
const unsigned tableSize = 1 << nbBits;
|
||||
const unsigned tableMask = tableSize - 1;
|
||||
const unsigned maxSymbolValue = tableMask;
|
||||
void* const ptr = ct;
|
||||
U16* const tableU16 = ( (U16*) ptr) + 2;
|
||||
void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableSize>>1); /* assumption : tableLog >= 1 */
|
||||
FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);
|
||||
unsigned s;
|
||||
|
||||
/* Sanity checks */
|
||||
if (nbBits < 1) return ERROR(GENERIC); /* min size */
|
||||
|
||||
/* header */
|
||||
tableU16[-2] = (U16) nbBits;
|
||||
tableU16[-1] = (U16) maxSymbolValue;
|
||||
|
||||
/* Build table */
|
||||
for (s=0; s<tableSize; s++)
|
||||
tableU16[s] = (U16)(tableSize + s);
|
||||
|
||||
/* Build Symbol Transformation Table */
|
||||
{ const U32 deltaNbBits = (nbBits << 16) - (1 << nbBits);
|
||||
for (s=0; s<=maxSymbolValue; s++) {
|
||||
symbolTT[s].deltaNbBits = deltaNbBits;
|
||||
symbolTT[s].deltaFindState = s-1;
|
||||
} }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fake FSE_CTable, for rle input (always same symbol) */
|
||||
size_t FSE_buildCTable_rle (FSE_CTable* ct, BYTE symbolValue)
|
||||
{
|
||||
@@ -665,78 +621,4 @@ size_t FSE_compress_usingCTable (void* dst, size_t dstSize,
|
||||
|
||||
size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); }
|
||||
|
||||
#ifndef ZSTD_NO_UNUSED_FUNCTIONS
|
||||
/* FSE_compress_wksp() :
|
||||
* Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
|
||||
* `wkspSize` size must be `(1<<tableLog)`.
|
||||
*/
|
||||
size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*) dst;
|
||||
BYTE* op = ostart;
|
||||
BYTE* const oend = ostart + dstSize;
|
||||
|
||||
unsigned count[FSE_MAX_SYMBOL_VALUE+1];
|
||||
S16 norm[FSE_MAX_SYMBOL_VALUE+1];
|
||||
FSE_CTable* CTable = (FSE_CTable*)workSpace;
|
||||
size_t const CTableSize = FSE_CTABLE_SIZE_U32(tableLog, maxSymbolValue);
|
||||
void* scratchBuffer = (void*)(CTable + CTableSize);
|
||||
size_t const scratchBufferSize = wkspSize - (CTableSize * sizeof(FSE_CTable));
|
||||
|
||||
/* init conditions */
|
||||
if (wkspSize < FSE_COMPRESS_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge);
|
||||
if (srcSize <= 1) return 0; /* Not compressible */
|
||||
if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
|
||||
if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG;
|
||||
|
||||
/* Scan input and build symbol stats */
|
||||
{ CHECK_V_F(maxCount, HIST_count_wksp(count, &maxSymbolValue, src, srcSize, scratchBuffer, scratchBufferSize) );
|
||||
if (maxCount == srcSize) return 1; /* only a single symbol in src : rle */
|
||||
if (maxCount == 1) return 0; /* each symbol present maximum once => not compressible */
|
||||
if (maxCount < (srcSize >> 7)) return 0; /* Heuristic : not compressible enough */
|
||||
}
|
||||
|
||||
tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue);
|
||||
CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue, /* useLowProbCount */ srcSize >= 2048) );
|
||||
|
||||
/* Write table description header */
|
||||
{ CHECK_V_F(nc_err, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) );
|
||||
op += nc_err;
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, scratchBufferSize) );
|
||||
{ CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, src, srcSize, CTable) );
|
||||
if (cSize == 0) return 0; /* not enough space for compressed data */
|
||||
op += cSize;
|
||||
}
|
||||
|
||||
/* check compressibility */
|
||||
if ( (size_t)(op-ostart) >= srcSize-1 ) return 0;
|
||||
|
||||
return op-ostart;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
FSE_CTable CTable_max[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)];
|
||||
union {
|
||||
U32 hist_wksp[HIST_WKSP_SIZE_U32];
|
||||
BYTE scratchBuffer[1 << FSE_MAX_TABLELOG];
|
||||
} workspace;
|
||||
} fseWkspMax_t;
|
||||
|
||||
size_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog)
|
||||
{
|
||||
fseWkspMax_t scratchBuffer;
|
||||
DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_COMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */
|
||||
if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
|
||||
return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer));
|
||||
}
|
||||
|
||||
size_t FSE_compress (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
return FSE_compress2(dst, dstCapacity, src, srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FSE_COMMONDEFS_ONLY */
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* hist : Histogram functions
|
||||
* part of Finite State Entropy project
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* hist : Histogram functions
|
||||
* part of Finite State Entropy project
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
|
||||
+72
-134
@@ -1,6 +1,6 @@
|
||||
/* ******************************************************************
|
||||
* Huffman encoder, part of New Generation Entropy library
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "hist.h"
|
||||
#define FSE_STATIC_LINKING_ONLY /* FSE_optimalTableLog_internal */
|
||||
#include "../common/fse.h" /* header compression */
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "../common/huf.h"
|
||||
#include "../common/error_private.h"
|
||||
#include "../common/bits.h" /* ZSTD_highbit32 */
|
||||
@@ -236,6 +235,8 @@ size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,
|
||||
U32 n;
|
||||
HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));
|
||||
|
||||
HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE >= sizeof(HUF_WriteCTableWksp));
|
||||
|
||||
/* check conditions */
|
||||
if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC);
|
||||
if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);
|
||||
@@ -265,16 +266,6 @@ size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,
|
||||
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)
|
||||
{
|
||||
@@ -386,7 +377,7 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 targetNbBits
|
||||
|
||||
/* renorm totalCost from 2^largestBits to 2^targetNbBits
|
||||
* note : totalCost is necessarily a multiple of baseCost */
|
||||
assert((totalCost & (baseCost - 1)) == 0);
|
||||
assert(((U32)totalCost & (baseCost - 1)) == 0);
|
||||
totalCost >>= (largestBits - targetNbBits);
|
||||
assert(totalCost > 0);
|
||||
|
||||
@@ -486,7 +477,7 @@ typedef struct {
|
||||
U16 curr;
|
||||
} rankPos;
|
||||
|
||||
typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
|
||||
typedef nodeElt huffNodeTable[2 * (HUF_SYMBOLVALUE_MAX + 1)];
|
||||
|
||||
/* Number of buckets available for HUF_sort() */
|
||||
#define RANK_POSITION_TABLE_SIZE 192
|
||||
@@ -505,8 +496,8 @@ typedef struct {
|
||||
* Let buckets 166 to 192 represent all remaining counts up to RANK_POSITION_MAX_COUNT_LOG using log2 bucketing.
|
||||
*/
|
||||
#define RANK_POSITION_MAX_COUNT_LOG 32
|
||||
#define RANK_POSITION_LOG_BUCKETS_BEGIN (RANK_POSITION_TABLE_SIZE - 1) - RANK_POSITION_MAX_COUNT_LOG - 1 /* == 158 */
|
||||
#define RANK_POSITION_DISTINCT_COUNT_CUTOFF RANK_POSITION_LOG_BUCKETS_BEGIN + ZSTD_highbit32(RANK_POSITION_LOG_BUCKETS_BEGIN) /* == 166 */
|
||||
#define RANK_POSITION_LOG_BUCKETS_BEGIN ((RANK_POSITION_TABLE_SIZE - 1) - RANK_POSITION_MAX_COUNT_LOG - 1 /* == 158 */)
|
||||
#define RANK_POSITION_DISTINCT_COUNT_CUTOFF (RANK_POSITION_LOG_BUCKETS_BEGIN + ZSTD_highbit32(RANK_POSITION_LOG_BUCKETS_BEGIN) /* == 166 */)
|
||||
|
||||
/* Return the appropriate bucket index for a given count. See definition of
|
||||
* RANK_POSITION_DISTINCT_COUNT_CUTOFF for explanation of bucketing strategy.
|
||||
@@ -745,6 +736,8 @@ HUF_buildCTable_wksp(HUF_CElt* CTable, const unsigned* count, U32 maxSymbolValue
|
||||
nodeElt* const huffNode = huffNode0+1;
|
||||
int nonNullRank;
|
||||
|
||||
HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE == sizeof(HUF_buildCTable_wksp_tables));
|
||||
|
||||
DEBUGLOG(5, "HUF_buildCTable_wksp (alphabet size = %u)", maxSymbolValue+1);
|
||||
|
||||
/* safety checks */
|
||||
@@ -1112,9 +1105,9 @@ HUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize,
|
||||
static size_t
|
||||
HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
const HUF_CElt* CTable, const int bmi2)
|
||||
const HUF_CElt* CTable, const int flags)
|
||||
{
|
||||
if (bmi2) {
|
||||
if (flags & HUF_flags_bmi2) {
|
||||
return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable);
|
||||
}
|
||||
return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable);
|
||||
@@ -1125,28 +1118,23 @@ HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
static size_t
|
||||
HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
const HUF_CElt* CTable, const int bmi2)
|
||||
const HUF_CElt* CTable, const int flags)
|
||||
{
|
||||
(void)bmi2;
|
||||
(void)flags;
|
||||
return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
|
||||
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags)
|
||||
{
|
||||
return HUF_compress1X_usingCTable_bmi2(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
size_t HUF_compress1X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2)
|
||||
{
|
||||
return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, bmi2);
|
||||
return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags);
|
||||
}
|
||||
|
||||
static size_t
|
||||
HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
const HUF_CElt* CTable, int bmi2)
|
||||
const HUF_CElt* CTable, int flags)
|
||||
{
|
||||
size_t const segmentSize = (srcSize+3)/4; /* first 3 segments */
|
||||
const BYTE* ip = (const BYTE*) src;
|
||||
@@ -1160,7 +1148,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
op += 6; /* jumpTable */
|
||||
|
||||
assert(op <= oend);
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );
|
||||
if (cSize == 0 || cSize > 65535) return 0;
|
||||
MEM_writeLE16(ostart, (U16)cSize);
|
||||
op += cSize;
|
||||
@@ -1168,7 +1156,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
|
||||
ip += segmentSize;
|
||||
assert(op <= oend);
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );
|
||||
if (cSize == 0 || cSize > 65535) return 0;
|
||||
MEM_writeLE16(ostart+2, (U16)cSize);
|
||||
op += cSize;
|
||||
@@ -1176,7 +1164,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
|
||||
ip += segmentSize;
|
||||
assert(op <= oend);
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );
|
||||
if (cSize == 0 || cSize > 65535) return 0;
|
||||
MEM_writeLE16(ostart+4, (U16)cSize);
|
||||
op += cSize;
|
||||
@@ -1185,7 +1173,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
ip += segmentSize;
|
||||
assert(op <= oend);
|
||||
assert(ip <= iend);
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, bmi2) );
|
||||
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, flags) );
|
||||
if (cSize == 0 || cSize > 65535) return 0;
|
||||
op += cSize;
|
||||
}
|
||||
@@ -1193,14 +1181,9 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
|
||||
return (size_t)(op-ostart);
|
||||
}
|
||||
|
||||
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, int flags)
|
||||
{
|
||||
return HUF_compress4X_usingCTable_bmi2(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
size_t HUF_compress4X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2)
|
||||
{
|
||||
return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, bmi2);
|
||||
return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags);
|
||||
}
|
||||
|
||||
typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;
|
||||
@@ -1208,11 +1191,11 @@ typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;
|
||||
static size_t HUF_compressCTable_internal(
|
||||
BYTE* const ostart, BYTE* op, BYTE* const oend,
|
||||
const void* src, size_t srcSize,
|
||||
HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2)
|
||||
HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int flags)
|
||||
{
|
||||
size_t const cSize = (nbStreams==HUF_singleStream) ?
|
||||
HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2) :
|
||||
HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2);
|
||||
HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags) :
|
||||
HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags);
|
||||
if (HUF_isError(cSize)) { return cSize; }
|
||||
if (cSize==0) { return 0; } /* uncompressible */
|
||||
op += cSize;
|
||||
@@ -1253,41 +1236,59 @@ unsigned HUF_minTableLog(unsigned symbolCardinality)
|
||||
return minBitsSymbols;
|
||||
}
|
||||
|
||||
unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, void* workSpace, size_t wkspSize, HUF_CElt* table, const unsigned* count, HUF_depth_mode depthMode)
|
||||
unsigned HUF_optimalTableLog(
|
||||
unsigned maxTableLog,
|
||||
size_t srcSize,
|
||||
unsigned maxSymbolValue,
|
||||
void* workSpace, size_t wkspSize,
|
||||
HUF_CElt* table,
|
||||
const unsigned* count,
|
||||
int flags)
|
||||
{
|
||||
unsigned optLog = FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);
|
||||
assert(srcSize > 1); /* Not supported, RLE should be used instead */
|
||||
assert(wkspSize >= sizeof(HUF_buildCTable_wksp_tables));
|
||||
|
||||
if (depthMode == HUF_depth_optimal) { /** Test valid depths and return optimal **/
|
||||
BYTE* dst = (BYTE*)workSpace + sizeof(HUF_WriteCTableWksp);
|
||||
if (!(flags & HUF_flags_optimalDepth)) {
|
||||
/* cheap evaluation, based on FSE */
|
||||
return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);
|
||||
}
|
||||
|
||||
{ BYTE* dst = (BYTE*)workSpace + sizeof(HUF_WriteCTableWksp);
|
||||
size_t dstSize = wkspSize - sizeof(HUF_WriteCTableWksp);
|
||||
size_t optSize = ((size_t) ~0);
|
||||
unsigned huffLog;
|
||||
size_t maxBits, hSize, newSize;
|
||||
const unsigned symbolCardinality = HUF_cardinality(count, maxSymbolValue);
|
||||
const unsigned minTableLog = HUF_minTableLog(symbolCardinality);
|
||||
size_t optSize = ((size_t) ~0) - 1;
|
||||
unsigned optLog = maxTableLog, optLogGuess;
|
||||
|
||||
if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) return optLog;
|
||||
DEBUGLOG(6, "HUF_optimalTableLog: probing huf depth (srcSize=%zu)", srcSize);
|
||||
|
||||
for (huffLog = HUF_minTableLog(symbolCardinality); huffLog <= maxTableLog; huffLog++) {
|
||||
maxBits = HUF_buildCTable_wksp(table, count,
|
||||
maxSymbolValue, huffLog,
|
||||
workSpace, wkspSize);
|
||||
/* Search until size increases */
|
||||
for (optLogGuess = minTableLog; optLogGuess <= maxTableLog; optLogGuess++) {
|
||||
DEBUGLOG(7, "checking for huffLog=%u", optLogGuess);
|
||||
maxBits = HUF_buildCTable_wksp(table, count, maxSymbolValue, optLogGuess, workSpace, wkspSize);
|
||||
if (ERR_isError(maxBits)) continue;
|
||||
|
||||
hSize = HUF_writeCTable_wksp(dst, dstSize, table, maxSymbolValue, (U32)maxBits,
|
||||
workSpace, wkspSize);
|
||||
if (maxBits < optLogGuess && optLogGuess > minTableLog) break;
|
||||
|
||||
hSize = HUF_writeCTable_wksp(dst, dstSize, table, maxSymbolValue, (U32)maxBits, workSpace, wkspSize);
|
||||
|
||||
if (ERR_isError(hSize)) continue;
|
||||
|
||||
newSize = HUF_estimateCompressedSize(table, count, maxSymbolValue) + hSize;
|
||||
|
||||
if (newSize > optSize + 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (newSize < optSize) {
|
||||
optSize = newSize;
|
||||
optLog = huffLog;
|
||||
optLog = optLogGuess;
|
||||
}
|
||||
}
|
||||
assert(optLog <= HUF_TABLELOG_MAX);
|
||||
return optLog;
|
||||
}
|
||||
assert(optLog <= HUF_TABLELOG_MAX);
|
||||
return optLog;
|
||||
}
|
||||
|
||||
/* HUF_compress_internal() :
|
||||
@@ -1299,8 +1300,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog,
|
||||
HUF_nbStreams_e nbStreams,
|
||||
void* workSpace, size_t wkspSize,
|
||||
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
|
||||
const int bmi2, unsigned suspectUncompressible, HUF_depth_mode depthMode)
|
||||
HUF_CElt* oldHufTable, HUF_repeat* repeat, int flags)
|
||||
{
|
||||
HUF_compress_tables_t* const table = (HUF_compress_tables_t*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(size_t));
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
@@ -1321,15 +1321,15 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||
if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;
|
||||
|
||||
/* Heuristic : If old table is valid, use it for small inputs */
|
||||
if (preferRepeat && repeat && *repeat == HUF_repeat_valid) {
|
||||
if ((flags & HUF_flags_preferRepeat) && repeat && *repeat == HUF_repeat_valid) {
|
||||
return HUF_compressCTable_internal(ostart, op, oend,
|
||||
src, srcSize,
|
||||
nbStreams, oldHufTable, bmi2);
|
||||
nbStreams, oldHufTable, flags);
|
||||
}
|
||||
|
||||
/* If uncompressible data is suspected, do a smaller sampling first */
|
||||
DEBUG_STATIC_ASSERT(SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO >= 2);
|
||||
if (suspectUncompressible && srcSize >= (SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE * SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO)) {
|
||||
if ((flags & HUF_flags_suspectUncompressible) && srcSize >= (SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE * SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO)) {
|
||||
size_t largestTotal = 0;
|
||||
DEBUGLOG(5, "input suspected incompressible : sampling to check");
|
||||
{ unsigned maxSymbolValueBegin = maxSymbolValue;
|
||||
@@ -1357,14 +1357,14 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||
*repeat = HUF_repeat_none;
|
||||
}
|
||||
/* Heuristic : use existing table for small inputs */
|
||||
if (preferRepeat && repeat && *repeat != HUF_repeat_none) {
|
||||
if ((flags & HUF_flags_preferRepeat) && repeat && *repeat != HUF_repeat_none) {
|
||||
return HUF_compressCTable_internal(ostart, op, oend,
|
||||
src, srcSize,
|
||||
nbStreams, oldHufTable, bmi2);
|
||||
nbStreams, oldHufTable, flags);
|
||||
}
|
||||
|
||||
/* Build Huffman Tree */
|
||||
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, &table->wksps, sizeof(table->wksps), table->CTable, table->count, depthMode);
|
||||
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, &table->wksps, sizeof(table->wksps), table->CTable, table->count, flags);
|
||||
{ size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,
|
||||
maxSymbolValue, huffLog,
|
||||
&table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp));
|
||||
@@ -1389,7 +1389,7 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||
if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {
|
||||
return HUF_compressCTable_internal(ostart, op, oend,
|
||||
src, srcSize,
|
||||
nbStreams, oldHufTable, bmi2);
|
||||
nbStreams, oldHufTable, flags);
|
||||
} }
|
||||
|
||||
/* Use the new huffman table */
|
||||
@@ -1401,48 +1401,20 @@ HUF_compress_internal (void* dst, size_t dstSize,
|
||||
}
|
||||
return HUF_compressCTable_internal(ostart, op, oend,
|
||||
src, srcSize,
|
||||
nbStreams, table->CTable, bmi2);
|
||||
}
|
||||
|
||||
|
||||
size_t HUF_compress1X_wksp (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog,
|
||||
void* workSpace, size_t wkspSize)
|
||||
{
|
||||
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
||||
maxSymbolValue, huffLog, HUF_singleStream,
|
||||
workSpace, wkspSize,
|
||||
NULL, NULL, 0, 0 /*bmi2*/, 0, HUF_depth_fast);
|
||||
nbStreams, table->CTable, flags);
|
||||
}
|
||||
|
||||
size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog,
|
||||
void* workSpace, size_t wkspSize,
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat,
|
||||
int bmi2, unsigned suspectUncompressible, HUF_depth_mode depthMode)
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int flags)
|
||||
{
|
||||
DEBUGLOG(5, "HUF_compress1X_repeat (srcSize = %zu)", srcSize);
|
||||
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
||||
maxSymbolValue, huffLog, HUF_singleStream,
|
||||
workSpace, wkspSize, hufTable,
|
||||
repeat, preferRepeat, bmi2, suspectUncompressible, depthMode);
|
||||
}
|
||||
|
||||
/* HUF_compress4X_repeat():
|
||||
* compress input using 4 streams.
|
||||
* provide workspace to generate compression tables */
|
||||
size_t HUF_compress4X_wksp (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog,
|
||||
void* workSpace, size_t wkspSize)
|
||||
{
|
||||
DEBUGLOG(5, "HUF_compress4X_wksp (srcSize = %zu)", srcSize);
|
||||
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
||||
maxSymbolValue, huffLog, HUF_fourStreams,
|
||||
workSpace, wkspSize,
|
||||
NULL, NULL, 0, 0 /*bmi2*/, 0, HUF_depth_fast);
|
||||
repeat, flags);
|
||||
}
|
||||
|
||||
/* HUF_compress4X_repeat():
|
||||
@@ -1453,45 +1425,11 @@ size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog,
|
||||
void* workSpace, size_t wkspSize,
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2,
|
||||
unsigned suspectUncompressible, HUF_depth_mode depthMode)
|
||||
HUF_CElt* hufTable, HUF_repeat* repeat, int flags)
|
||||
{
|
||||
DEBUGLOG(5, "HUF_compress4X_repeat (srcSize = %zu)", srcSize);
|
||||
return HUF_compress_internal(dst, dstSize, src, srcSize,
|
||||
maxSymbolValue, huffLog, HUF_fourStreams,
|
||||
workSpace, wkspSize,
|
||||
hufTable, repeat, preferRepeat, bmi2, suspectUncompressible, depthMode);
|
||||
hufTable, repeat, flags);
|
||||
}
|
||||
|
||||
#ifndef ZSTD_NO_UNUSED_FUNCTIONS
|
||||
/** HUF_buildCTable() :
|
||||
* @return : maxNbBits
|
||||
* Note : count is used before tree is written, so they can safely overlap
|
||||
*/
|
||||
size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits)
|
||||
{
|
||||
HUF_buildCTable_wksp_tables workspace;
|
||||
return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace));
|
||||
}
|
||||
|
||||
size_t HUF_compress1X (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog)
|
||||
{
|
||||
U64 workSpace[HUF_WORKSPACE_SIZE_U64];
|
||||
return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_compress2 (void* dst, size_t dstSize,
|
||||
const void* src, size_t srcSize,
|
||||
unsigned maxSymbolValue, unsigned huffLog)
|
||||
{
|
||||
U64 workSpace[HUF_WORKSPACE_SIZE_U64];
|
||||
return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
|
||||
{
|
||||
return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT);
|
||||
}
|
||||
#endif
|
||||
|
||||
+686
-289
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "hist.h" /* HIST_countFast_wksp */
|
||||
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
|
||||
#include "../common/fse.h"
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "../common/huf.h"
|
||||
#include "zstd_compress_internal.h"
|
||||
#include "zstd_compress_sequences.h"
|
||||
@@ -59,14 +58,17 @@
|
||||
* Helper functions
|
||||
***************************************/
|
||||
/* ZSTD_compressBound()
|
||||
* Note that the result from this function is only compatible with the "normal"
|
||||
* full-block strategy.
|
||||
* When there are a lot of small blocks due to frequent flush in streaming mode
|
||||
* the overhead of headers can make the compressed data to be larger than the
|
||||
* return value of ZSTD_compressBound().
|
||||
* Note that the result from this function is only valid for
|
||||
* the one-pass compression functions.
|
||||
* When employing the streaming mode,
|
||||
* if flushes are frequently altering the size of blocks,
|
||||
* the overhead from block headers can make the compressed data larger
|
||||
* than the return value of ZSTD_compressBound().
|
||||
*/
|
||||
size_t ZSTD_compressBound(size_t srcSize) {
|
||||
return ZSTD_COMPRESSBOUND(srcSize);
|
||||
size_t const r = ZSTD_COMPRESSBOUND(srcSize);
|
||||
if (r==0) return ERROR(srcSize_wrong);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -275,6 +277,28 @@ static ZSTD_paramSwitch_e ZSTD_resolveEnableLdm(ZSTD_paramSwitch_e mode,
|
||||
return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable;
|
||||
}
|
||||
|
||||
static int ZSTD_resolveExternalSequenceValidation(int mode) {
|
||||
return mode;
|
||||
}
|
||||
|
||||
/* Resolves maxBlockSize to the default if no value is present. */
|
||||
static size_t ZSTD_resolveMaxBlockSize(size_t maxBlockSize) {
|
||||
if (maxBlockSize == 0) {
|
||||
return ZSTD_BLOCKSIZE_MAX;
|
||||
} else {
|
||||
return maxBlockSize;
|
||||
}
|
||||
}
|
||||
|
||||
static ZSTD_paramSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_paramSwitch_e value, int cLevel) {
|
||||
if (value != ZSTD_ps_auto) return value;
|
||||
if (cLevel < 10) {
|
||||
return ZSTD_ps_disable;
|
||||
} else {
|
||||
return ZSTD_ps_enable;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns 1 if compression parameters are such that CDict hashtable and chaintable indices are tagged.
|
||||
* If so, the tags need to be removed in ZSTD_resetCCtx_byCopyingCDict. */
|
||||
static int ZSTD_CDictIndicesAreTagged(const ZSTD_compressionParameters* const cParams) {
|
||||
@@ -298,6 +322,10 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
|
||||
}
|
||||
cctxParams.useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams.useBlockSplitter, &cParams);
|
||||
cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);
|
||||
cctxParams.validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams.validateSequences);
|
||||
cctxParams.maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams.maxBlockSize);
|
||||
cctxParams.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams.searchForExternalRepcodes,
|
||||
cctxParams.compressionLevel);
|
||||
assert(!ZSTD_checkCParams(cParams));
|
||||
return cctxParams;
|
||||
}
|
||||
@@ -343,10 +371,13 @@ size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel)
|
||||
#define ZSTD_NO_CLEVEL 0
|
||||
|
||||
/**
|
||||
* Initializes the cctxParams from params and compressionLevel.
|
||||
* Initializes `cctxParams` from `params` and `compressionLevel`.
|
||||
* @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL.
|
||||
*/
|
||||
static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_parameters const* params, int compressionLevel)
|
||||
static void
|
||||
ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams,
|
||||
const ZSTD_parameters* params,
|
||||
int compressionLevel)
|
||||
{
|
||||
assert(!ZSTD_checkCParams(params->cParams));
|
||||
ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));
|
||||
@@ -359,6 +390,9 @@ static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_par
|
||||
cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, ¶ms->cParams);
|
||||
cctxParams->useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->useBlockSplitter, ¶ms->cParams);
|
||||
cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, ¶ms->cParams);
|
||||
cctxParams->validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams->validateSequences);
|
||||
cctxParams->maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams->maxBlockSize);
|
||||
cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, compressionLevel);
|
||||
DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d, useBlockSplitter=%d ldm=%d",
|
||||
cctxParams->useRowMatchFinder, cctxParams->useBlockSplitter, cctxParams->ldmParams.enableLdm);
|
||||
}
|
||||
@@ -373,7 +407,7 @@ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_paramete
|
||||
|
||||
/**
|
||||
* Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone.
|
||||
* @param param Validated zstd parameters.
|
||||
* @param params Validated zstd parameters.
|
||||
*/
|
||||
static void ZSTD_CCtxParams_setZstdParams(
|
||||
ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)
|
||||
@@ -581,6 +615,21 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_enableMatchFinderFallback:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_maxBlockSize:
|
||||
bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;
|
||||
bounds.upperBound = ZSTD_BLOCKSIZE_MAX;
|
||||
return bounds;
|
||||
|
||||
case ZSTD_c_searchForExternalRepcodes:
|
||||
bounds.lowerBound = (int)ZSTD_ps_auto;
|
||||
bounds.upperBound = (int)ZSTD_ps_disable;
|
||||
return bounds;
|
||||
|
||||
default:
|
||||
bounds.error = ERROR(parameter_unsupported);
|
||||
return bounds;
|
||||
@@ -646,6 +695,9 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
|
||||
case ZSTD_c_useRowMatchFinder:
|
||||
case ZSTD_c_deterministicRefPrefix:
|
||||
case ZSTD_c_prefetchCDictTables:
|
||||
case ZSTD_c_enableMatchFinderFallback:
|
||||
case ZSTD_c_maxBlockSize:
|
||||
case ZSTD_c_searchForExternalRepcodes:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -658,7 +710,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
||||
if (ZSTD_isUpdateAuthorized(param)) {
|
||||
cctx->cParamsChanged = 1;
|
||||
} else {
|
||||
RETURN_ERROR(stage_wrong, "can only set params in ctx init stage");
|
||||
RETURN_ERROR(stage_wrong, "can only set params in cctx init stage");
|
||||
} }
|
||||
|
||||
switch(param)
|
||||
@@ -702,6 +754,9 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
|
||||
case ZSTD_c_useRowMatchFinder:
|
||||
case ZSTD_c_deterministicRefPrefix:
|
||||
case ZSTD_c_prefetchCDictTables:
|
||||
case ZSTD_c_enableMatchFinderFallback:
|
||||
case ZSTD_c_maxBlockSize:
|
||||
case ZSTD_c_searchForExternalRepcodes:
|
||||
break;
|
||||
|
||||
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
||||
@@ -793,14 +848,14 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
|
||||
case ZSTD_c_forceAttachDict : {
|
||||
const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value;
|
||||
BOUNDCHECK(ZSTD_c_forceAttachDict, pref);
|
||||
BOUNDCHECK(ZSTD_c_forceAttachDict, (int)pref);
|
||||
CCtxParams->attachDictPref = pref;
|
||||
return CCtxParams->attachDictPref;
|
||||
}
|
||||
|
||||
case ZSTD_c_literalCompressionMode : {
|
||||
const ZSTD_paramSwitch_e lcm = (ZSTD_paramSwitch_e)value;
|
||||
BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
|
||||
BOUNDCHECK(ZSTD_c_literalCompressionMode, (int)lcm);
|
||||
CCtxParams->literalCompressionMode = lcm;
|
||||
return CCtxParams->literalCompressionMode;
|
||||
}
|
||||
@@ -934,6 +989,22 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
|
||||
CCtxParams->prefetchCDictTables = (ZSTD_paramSwitch_e)value;
|
||||
return CCtxParams->prefetchCDictTables;
|
||||
|
||||
case ZSTD_c_enableMatchFinderFallback:
|
||||
BOUNDCHECK(ZSTD_c_enableMatchFinderFallback, value);
|
||||
CCtxParams->enableMatchFinderFallback = value;
|
||||
return CCtxParams->enableMatchFinderFallback;
|
||||
|
||||
case ZSTD_c_maxBlockSize:
|
||||
if (value!=0) /* 0 ==> default */
|
||||
BOUNDCHECK(ZSTD_c_maxBlockSize, value);
|
||||
CCtxParams->maxBlockSize = value;
|
||||
return CCtxParams->maxBlockSize;
|
||||
|
||||
case ZSTD_c_searchForExternalRepcodes:
|
||||
BOUNDCHECK(ZSTD_c_searchForExternalRepcodes, value);
|
||||
CCtxParams->searchForExternalRepcodes = (ZSTD_paramSwitch_e)value;
|
||||
return CCtxParams->searchForExternalRepcodes;
|
||||
|
||||
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
||||
}
|
||||
}
|
||||
@@ -1069,6 +1140,15 @@ size_t ZSTD_CCtxParams_getParameter(
|
||||
case ZSTD_c_prefetchCDictTables:
|
||||
*value = (int)CCtxParams->prefetchCDictTables;
|
||||
break;
|
||||
case ZSTD_c_enableMatchFinderFallback:
|
||||
*value = CCtxParams->enableMatchFinderFallback;
|
||||
break;
|
||||
case ZSTD_c_maxBlockSize:
|
||||
*value = (int)CCtxParams->maxBlockSize;
|
||||
break;
|
||||
case ZSTD_c_searchForExternalRepcodes:
|
||||
*value = (int)CCtxParams->searchForExternalRepcodes;
|
||||
break;
|
||||
default: RETURN_ERROR(parameter_unsupported, "unknown parameter");
|
||||
}
|
||||
return 0;
|
||||
@@ -1095,6 +1175,21 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_CCtx_setCParams");
|
||||
assert(cctx != NULL);
|
||||
if (cctx->streamStage != zcss_init) {
|
||||
/* All parameters in @cparams are allowed to be updated during MT compression.
|
||||
* This must be signaled, so that MT compression picks up the changes */
|
||||
cctx->cParamsChanged = 1;
|
||||
}
|
||||
/* only update if parameters are valid */
|
||||
FORWARD_IF_ERROR(ZSTD_checkCParams(cparams), "");
|
||||
cctx->requestedParams.cParams = cparams;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %llu bytes", pledgedSrcSize);
|
||||
@@ -1240,6 +1335,7 @@ size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)
|
||||
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
|
||||
"Can't reset parameters only when not in init stage.");
|
||||
ZSTD_clearAllDicts(cctx);
|
||||
ZSTD_memset(&cctx->externalMatchCtx, 0, sizeof(cctx->externalMatchCtx));
|
||||
return ZSTD_CCtxParams_reset(&cctx->requestedParams);
|
||||
}
|
||||
return 0;
|
||||
@@ -1336,7 +1432,8 @@ static ZSTD_compressionParameters
|
||||
ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
||||
unsigned long long srcSize,
|
||||
size_t dictSize,
|
||||
ZSTD_cParamMode_e mode)
|
||||
ZSTD_cParamMode_e mode,
|
||||
ZSTD_paramSwitch_e useRowMatchFinder)
|
||||
{
|
||||
const U64 minSrcSize = 513; /* (1<<9) + 1 */
|
||||
const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);
|
||||
@@ -1370,8 +1467,8 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
||||
}
|
||||
|
||||
/* resize windowLog if input is small enough, to use less memory */
|
||||
if ( (srcSize < maxWindowResize)
|
||||
&& (dictSize < maxWindowResize) ) {
|
||||
if ( (srcSize <= maxWindowResize)
|
||||
&& (dictSize <= maxWindowResize) ) {
|
||||
U32 const tSize = (U32)(srcSize + dictSize);
|
||||
static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;
|
||||
U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :
|
||||
@@ -1389,11 +1486,40 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
|
||||
if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)
|
||||
cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN; /* minimum wlog required for valid frame header */
|
||||
|
||||
/* We can't use more than 32 bits of hash in total, so that means that we require:
|
||||
* (hashLog + 8) <= 32 && (chainLog + 8) <= 32
|
||||
*/
|
||||
if (mode == ZSTD_cpm_createCDict && ZSTD_CDictIndicesAreTagged(&cPar)) {
|
||||
U32 const maxShortCacheHashLog = 32 - ZSTD_SHORT_CACHE_TAG_BITS;
|
||||
if (cPar.hashLog > maxShortCacheHashLog) {
|
||||
cPar.hashLog = maxShortCacheHashLog;
|
||||
}
|
||||
if (cPar.chainLog > maxShortCacheHashLog) {
|
||||
cPar.chainLog = maxShortCacheHashLog;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* At this point, we aren't 100% sure if we are using the row match finder.
|
||||
* Unless it is explicitly disabled, conservatively assume that it is enabled.
|
||||
* In this case it will only be disabled for small sources, so shrinking the
|
||||
* hash log a little bit shouldn't result in any ratio loss.
|
||||
*/
|
||||
if (useRowMatchFinder == ZSTD_ps_auto)
|
||||
useRowMatchFinder = ZSTD_ps_enable;
|
||||
|
||||
/* We can't hash more than 32-bits in total. So that means that we require:
|
||||
* (hashLog - rowLog + 8) <= 32
|
||||
*/
|
||||
if (ZSTD_rowMatchFinderUsed(cPar.strategy, useRowMatchFinder)) {
|
||||
/* Switch to 32-entry rows if searchLog is 5 (or more) */
|
||||
U32 const rowLog = BOUNDED(4, cPar.searchLog, 6);
|
||||
U32 const maxRowHashLog = 32 - ZSTD_ROW_HASH_TAG_BITS;
|
||||
U32 const maxHashLog = maxRowHashLog + rowLog;
|
||||
assert(cPar.hashLog >= rowLog);
|
||||
if (cPar.hashLog > maxHashLog) {
|
||||
cPar.hashLog = maxHashLog;
|
||||
}
|
||||
}
|
||||
|
||||
return cPar;
|
||||
@@ -1406,7 +1532,7 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar,
|
||||
{
|
||||
cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */
|
||||
if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;
|
||||
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown);
|
||||
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto);
|
||||
}
|
||||
|
||||
static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode);
|
||||
@@ -1437,7 +1563,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
|
||||
ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);
|
||||
assert(!ZSTD_checkCParams(cParams));
|
||||
/* srcSizeHint == 0 means 0 */
|
||||
return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode);
|
||||
return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode, CCtxParams->useRowMatchFinder);
|
||||
}
|
||||
|
||||
static size_t
|
||||
@@ -1482,6 +1608,13 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
|
||||
return tableSpace + optSpace + slackSpace + lazyAdditionalSpace;
|
||||
}
|
||||
|
||||
/* Helper function for calculating memory requirements.
|
||||
* Gives a tighter bound than ZSTD_sequenceBound() by taking minMatch into account. */
|
||||
static size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useExternalMatchFinder) {
|
||||
U32 const divider = (minMatch==3 || useExternalMatchFinder) ? 3 : 4;
|
||||
return blockSize / divider;
|
||||
}
|
||||
|
||||
static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
const ZSTD_compressionParameters* cParams,
|
||||
const ldmParams_t* ldmParams,
|
||||
@@ -1489,12 +1622,13 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
const ZSTD_paramSwitch_e useRowMatchFinder,
|
||||
const size_t buffInSize,
|
||||
const size_t buffOutSize,
|
||||
const U64 pledgedSrcSize)
|
||||
const U64 pledgedSrcSize,
|
||||
int useExternalMatchFinder,
|
||||
size_t maxBlockSize)
|
||||
{
|
||||
size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
|
||||
U32 const divider = (cParams->minMatch==3) ? 3 : 4;
|
||||
size_t const maxNbSeq = blockSize / divider;
|
||||
size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize);
|
||||
size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useExternalMatchFinder);
|
||||
size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)
|
||||
+ ZSTD_cwksp_aligned_alloc_size(maxNbSeq * sizeof(seqDef))
|
||||
+ 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));
|
||||
@@ -1513,6 +1647,11 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
|
||||
size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;
|
||||
|
||||
size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);
|
||||
size_t const externalSeqSpace = useExternalMatchFinder
|
||||
? ZSTD_cwksp_aligned_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence))
|
||||
: 0;
|
||||
|
||||
size_t const neededSpace =
|
||||
cctxSpace +
|
||||
entropySpace +
|
||||
@@ -1521,7 +1660,8 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
ldmSeqSpace +
|
||||
matchStateSize +
|
||||
tokenSpace +
|
||||
bufferSpace;
|
||||
bufferSpace +
|
||||
externalSeqSpace;
|
||||
|
||||
DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace);
|
||||
return neededSpace;
|
||||
@@ -1539,7 +1679,7 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
||||
* be needed. However, we still allocate two 0-sized buffers, which can
|
||||
* take space under ASAN. */
|
||||
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
&cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
&cParams, ¶ms->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, params->useExternalMatchFinder, params->maxBlockSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
|
||||
@@ -1589,7 +1729,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
||||
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
|
||||
{ ZSTD_compressionParameters const cParams =
|
||||
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
||||
size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), (size_t)1 << cParams.windowLog);
|
||||
size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)
|
||||
? ((size_t)1 << cParams.windowLog) + blockSize
|
||||
: 0;
|
||||
@@ -1600,7 +1740,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
|
||||
|
||||
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
&cParams, ¶ms->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
|
||||
ZSTD_CONTENTSIZE_UNKNOWN);
|
||||
ZSTD_CONTENTSIZE_UNKNOWN, params->useExternalMatchFinder, params->maxBlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1874,6 +2014,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
assert(params->useRowMatchFinder != ZSTD_ps_auto);
|
||||
assert(params->useBlockSplitter != ZSTD_ps_auto);
|
||||
assert(params->ldmParams.enableLdm != ZSTD_ps_auto);
|
||||
assert(params->maxBlockSize != 0);
|
||||
if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
|
||||
/* Adjust long distance matching parameters */
|
||||
ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, ¶ms->cParams);
|
||||
@@ -1882,9 +2023,8 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
}
|
||||
|
||||
{ size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize));
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
|
||||
U32 const divider = (params->cParams.minMatch==3) ? 3 : 4;
|
||||
size_t const maxNbSeq = blockSize / divider;
|
||||
size_t const blockSize = MIN(params->maxBlockSize, windowSize);
|
||||
size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, params->useExternalMatchFinder);
|
||||
size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered)
|
||||
? ZSTD_compressBound(blockSize) + 1
|
||||
: 0;
|
||||
@@ -1901,7 +2041,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
size_t const neededSpace =
|
||||
ZSTD_estimateCCtxSize_usingCCtxParams_internal(
|
||||
¶ms->cParams, ¶ms->ldmParams, zc->staticSize != 0, params->useRowMatchFinder,
|
||||
buffInSize, buffOutSize, pledgedSrcSize);
|
||||
buffInSize, buffOutSize, pledgedSrcSize, params->useExternalMatchFinder, params->maxBlockSize);
|
||||
int resizeWorkspace;
|
||||
|
||||
FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!");
|
||||
@@ -2014,6 +2154,14 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
zc->ldmState.loadedDictEnd = 0;
|
||||
}
|
||||
|
||||
/* reserve space for block-level external sequences */
|
||||
if (params->useExternalMatchFinder) {
|
||||
size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);
|
||||
zc->externalMatchCtx.seqBufferCapacity = maxNbExternalSeq;
|
||||
zc->externalMatchCtx.seqBuffer =
|
||||
(ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence));
|
||||
}
|
||||
|
||||
DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
|
||||
assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace, resizeWorkspace));
|
||||
|
||||
@@ -2087,7 +2235,8 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,
|
||||
}
|
||||
|
||||
params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize,
|
||||
cdict->dictContentSize, ZSTD_cpm_attachDict);
|
||||
cdict->dictContentSize, ZSTD_cpm_attachDict,
|
||||
params.useRowMatchFinder);
|
||||
params.cParams.windowLog = windowLog;
|
||||
params.useRowMatchFinder = cdict->useRowMatchFinder; /* cdict overrides */
|
||||
FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, ¶ms, pledgedSrcSize,
|
||||
@@ -2271,6 +2420,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
||||
params.useBlockSplitter = srcCCtx->appliedParams.useBlockSplitter;
|
||||
params.ldmParams = srcCCtx->appliedParams.ldmParams;
|
||||
params.fParams = fParams;
|
||||
params.maxBlockSize = srcCCtx->appliedParams.maxBlockSize;
|
||||
ZSTD_resetCCtx_internal(dstCCtx, ¶ms, pledgedSrcSize,
|
||||
/* loadedDictSize */ 0,
|
||||
ZSTDcrp_leaveDirty, zbuff);
|
||||
@@ -2430,7 +2580,7 @@ static void ZSTD_reduceIndex (ZSTD_matchState_t* ms, ZSTD_CCtx_params const* par
|
||||
|
||||
/* See doc/zstd_compression_format.md for detailed format description */
|
||||
|
||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
||||
int ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
||||
{
|
||||
const seqDef* const sequences = seqStorePtr->sequencesStart;
|
||||
BYTE* const llCodeTable = seqStorePtr->llCode;
|
||||
@@ -2438,18 +2588,24 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
|
||||
BYTE* const mlCodeTable = seqStorePtr->mlCode;
|
||||
U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||
U32 u;
|
||||
int longOffsets = 0;
|
||||
assert(nbSeq <= seqStorePtr->maxNbSeq);
|
||||
for (u=0; u<nbSeq; u++) {
|
||||
U32 const llv = sequences[u].litLength;
|
||||
U32 const ofCode = ZSTD_highbit32(sequences[u].offBase);
|
||||
U32 const mlv = sequences[u].mlBase;
|
||||
llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
|
||||
ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offBase);
|
||||
ofCodeTable[u] = (BYTE)ofCode;
|
||||
mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
|
||||
assert(!(MEM_64bits() && ofCode >= STREAM_ACCUMULATOR_MIN));
|
||||
if (MEM_32bits() && ofCode >= STREAM_ACCUMULATOR_MIN)
|
||||
longOffsets = 1;
|
||||
}
|
||||
if (seqStorePtr->longLengthType==ZSTD_llt_literalLength)
|
||||
llCodeTable[seqStorePtr->longLengthPos] = MaxLL;
|
||||
if (seqStorePtr->longLengthType==ZSTD_llt_matchLength)
|
||||
mlCodeTable[seqStorePtr->longLengthPos] = MaxML;
|
||||
return longOffsets;
|
||||
}
|
||||
|
||||
/* ZSTD_useTargetCBlockSize():
|
||||
@@ -2483,6 +2639,7 @@ typedef struct {
|
||||
U32 MLtype;
|
||||
size_t size;
|
||||
size_t lastCountSize; /* Accounts for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */
|
||||
int longOffsets;
|
||||
} ZSTD_symbolEncodingTypeStats_t;
|
||||
|
||||
/* ZSTD_buildSequencesStatistics():
|
||||
@@ -2493,11 +2650,13 @@ typedef struct {
|
||||
* entropyWkspSize must be of size at least ENTROPY_WORKSPACE_SIZE - (MaxSeq + 1)*sizeof(U32)
|
||||
*/
|
||||
static ZSTD_symbolEncodingTypeStats_t
|
||||
ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
|
||||
const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy,
|
||||
BYTE* dst, const BYTE* const dstEnd,
|
||||
ZSTD_strategy strategy, unsigned* countWorkspace,
|
||||
void* entropyWorkspace, size_t entropyWkspSize) {
|
||||
ZSTD_buildSequencesStatistics(
|
||||
const seqStore_t* seqStorePtr, size_t nbSeq,
|
||||
const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy,
|
||||
BYTE* dst, const BYTE* const dstEnd,
|
||||
ZSTD_strategy strategy, unsigned* countWorkspace,
|
||||
void* entropyWorkspace, size_t entropyWkspSize)
|
||||
{
|
||||
BYTE* const ostart = dst;
|
||||
const BYTE* const oend = dstEnd;
|
||||
BYTE* op = ostart;
|
||||
@@ -2511,7 +2670,7 @@ ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
|
||||
|
||||
stats.lastCountSize = 0;
|
||||
/* convert length/distances into codes */
|
||||
ZSTD_seqToCodes(seqStorePtr);
|
||||
stats.longOffsets = ZSTD_seqToCodes(seqStorePtr);
|
||||
assert(op <= oend);
|
||||
assert(nbSeq != 0); /* ZSTD_selectEncodingType() divides by nbSeq */
|
||||
/* build CTable for Literal Lengths */
|
||||
@@ -2616,22 +2775,22 @@ ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
|
||||
*/
|
||||
#define SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO 20
|
||||
MEM_STATIC size_t
|
||||
ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
|
||||
const ZSTD_entropyCTables_t* prevEntropy,
|
||||
ZSTD_entropyCTables_t* nextEntropy,
|
||||
const ZSTD_CCtx_params* cctxParams,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* entropyWorkspace, size_t entropyWkspSize,
|
||||
const int bmi2)
|
||||
ZSTD_entropyCompressSeqStore_internal(
|
||||
const seqStore_t* seqStorePtr,
|
||||
const ZSTD_entropyCTables_t* prevEntropy,
|
||||
ZSTD_entropyCTables_t* nextEntropy,
|
||||
const ZSTD_CCtx_params* cctxParams,
|
||||
void* dst, size_t dstCapacity,
|
||||
void* entropyWorkspace, size_t entropyWkspSize,
|
||||
const int bmi2)
|
||||
{
|
||||
const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;
|
||||
ZSTD_strategy const strategy = cctxParams->cParams.strategy;
|
||||
unsigned* count = (unsigned*)entropyWorkspace;
|
||||
FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;
|
||||
FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;
|
||||
FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;
|
||||
const seqDef* const sequences = seqStorePtr->sequencesStart;
|
||||
const size_t nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
||||
const size_t nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||
const BYTE* const ofCodeTable = seqStorePtr->ofCode;
|
||||
const BYTE* const llCodeTable = seqStorePtr->llCode;
|
||||
const BYTE* const mlCodeTable = seqStorePtr->mlCode;
|
||||
@@ -2639,6 +2798,7 @@ ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
|
||||
BYTE* const oend = ostart + dstCapacity;
|
||||
BYTE* op = ostart;
|
||||
size_t lastCountSize;
|
||||
int longOffsets = 0;
|
||||
|
||||
entropyWorkspace = count + (MaxSeq + 1);
|
||||
entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);
|
||||
@@ -2649,21 +2809,20 @@ ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
|
||||
|
||||
/* Compress literals */
|
||||
{ const BYTE* const literals = seqStorePtr->litStart;
|
||||
size_t const numSequences = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
||||
size_t const numLiterals = seqStorePtr->lit - seqStorePtr->litStart;
|
||||
size_t const numSequences = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||
size_t const numLiterals = (size_t)(seqStorePtr->lit - seqStorePtr->litStart);
|
||||
/* Base suspicion of uncompressibility on ratio of literals to sequences */
|
||||
unsigned const suspectUncompressible = (numSequences == 0) || (numLiterals / numSequences >= SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO);
|
||||
size_t const litSize = (size_t)(seqStorePtr->lit - literals);
|
||||
|
||||
HUF_depth_mode depthMode = cctxParams->cParams.strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD ? HUF_depth_optimal : HUF_depth_fast;
|
||||
size_t const cSize = ZSTD_compressLiterals(
|
||||
&prevEntropy->huf, &nextEntropy->huf,
|
||||
cctxParams->cParams.strategy,
|
||||
ZSTD_literalsCompressionIsDisabled(cctxParams),
|
||||
op, dstCapacity,
|
||||
literals, litSize,
|
||||
entropyWorkspace, entropyWkspSize,
|
||||
bmi2, suspectUncompressible, depthMode);
|
||||
&prevEntropy->huf, &nextEntropy->huf,
|
||||
cctxParams->cParams.strategy,
|
||||
ZSTD_literalsCompressionIsDisabled(cctxParams),
|
||||
suspectUncompressible, bmi2);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
|
||||
assert(cSize <= dstCapacity);
|
||||
op += cSize;
|
||||
@@ -2701,6 +2860,7 @@ ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
|
||||
*seqHead = (BYTE)((stats.LLtype<<6) + (stats.Offtype<<4) + (stats.MLtype<<2));
|
||||
lastCountSize = stats.lastCountSize;
|
||||
op += stats.size;
|
||||
longOffsets = stats.longOffsets;
|
||||
}
|
||||
|
||||
{ size_t const bitstreamSize = ZSTD_encodeSequences(
|
||||
@@ -2735,14 +2895,15 @@ ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
|
||||
}
|
||||
|
||||
MEM_STATIC size_t
|
||||
ZSTD_entropyCompressSeqStore(seqStore_t* seqStorePtr,
|
||||
const ZSTD_entropyCTables_t* prevEntropy,
|
||||
ZSTD_entropyCTables_t* nextEntropy,
|
||||
const ZSTD_CCtx_params* cctxParams,
|
||||
void* dst, size_t dstCapacity,
|
||||
size_t srcSize,
|
||||
void* entropyWorkspace, size_t entropyWkspSize,
|
||||
int bmi2)
|
||||
ZSTD_entropyCompressSeqStore(
|
||||
const seqStore_t* seqStorePtr,
|
||||
const ZSTD_entropyCTables_t* prevEntropy,
|
||||
ZSTD_entropyCTables_t* nextEntropy,
|
||||
const ZSTD_CCtx_params* cctxParams,
|
||||
void* dst, size_t dstCapacity,
|
||||
size_t srcSize,
|
||||
void* entropyWorkspace, size_t entropyWkspSize,
|
||||
int bmi2)
|
||||
{
|
||||
size_t const cSize = ZSTD_entropyCompressSeqStore_internal(
|
||||
seqStorePtr, prevEntropy, nextEntropy, cctxParams,
|
||||
@@ -2763,6 +2924,10 @@ ZSTD_entropyCompressSeqStore(seqStore_t* seqStorePtr,
|
||||
if (cSize >= maxCSize) return 0; /* block not compressed */
|
||||
}
|
||||
DEBUGLOG(5, "ZSTD_entropyCompressSeqStore() cSize: %zu", cSize);
|
||||
/* libzstd decoder before > v1.5.4 is not compatible with compressed blocks of size ZSTD_BLOCKSIZE_MAX exactly.
|
||||
* This restriction is indirectly already fulfilled by respecting ZSTD_minGain() condition above.
|
||||
*/
|
||||
assert(cSize < ZSTD_BLOCKSIZE_MAX);
|
||||
return cSize;
|
||||
}
|
||||
|
||||
@@ -2857,6 +3022,72 @@ void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
||||
ssPtr->longLengthType = ZSTD_llt_none;
|
||||
}
|
||||
|
||||
/* ZSTD_postProcessExternalMatchFinderResult() :
|
||||
* Validates and post-processes sequences obtained through the external matchfinder API:
|
||||
* - Checks whether nbExternalSeqs represents an error condition.
|
||||
* - Appends a block delimiter to outSeqs if one is not already present.
|
||||
* See zstd.h for context regarding block delimiters.
|
||||
* Returns the number of sequences after post-processing, or an error code. */
|
||||
static size_t ZSTD_postProcessExternalMatchFinderResult(
|
||||
ZSTD_Sequence* outSeqs, size_t nbExternalSeqs, size_t outSeqsCapacity, size_t srcSize
|
||||
) {
|
||||
RETURN_ERROR_IF(
|
||||
nbExternalSeqs > outSeqsCapacity,
|
||||
externalMatchFinder_failed,
|
||||
"External matchfinder returned error code %lu",
|
||||
(unsigned long)nbExternalSeqs
|
||||
);
|
||||
|
||||
RETURN_ERROR_IF(
|
||||
nbExternalSeqs == 0 && srcSize > 0,
|
||||
externalMatchFinder_failed,
|
||||
"External matchfinder produced zero sequences for a non-empty src buffer!"
|
||||
);
|
||||
|
||||
if (srcSize == 0) {
|
||||
ZSTD_memset(&outSeqs[0], 0, sizeof(ZSTD_Sequence));
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
ZSTD_Sequence const lastSeq = outSeqs[nbExternalSeqs - 1];
|
||||
|
||||
/* We can return early if lastSeq is already a block delimiter. */
|
||||
if (lastSeq.offset == 0 && lastSeq.matchLength == 0) {
|
||||
return nbExternalSeqs;
|
||||
}
|
||||
|
||||
/* This error condition is only possible if the external matchfinder
|
||||
* produced an invalid parse, by definition of ZSTD_sequenceBound(). */
|
||||
RETURN_ERROR_IF(
|
||||
nbExternalSeqs == outSeqsCapacity,
|
||||
externalMatchFinder_failed,
|
||||
"nbExternalSeqs == outSeqsCapacity but lastSeq is not a block delimiter!"
|
||||
);
|
||||
|
||||
/* lastSeq is not a block delimiter, so we need to append one. */
|
||||
ZSTD_memset(&outSeqs[nbExternalSeqs], 0, sizeof(ZSTD_Sequence));
|
||||
return nbExternalSeqs + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ZSTD_fastSequenceLengthSum() :
|
||||
* Returns sum(litLen) + sum(matchLen) + lastLits for *seqBuf*.
|
||||
* Similar to another function in zstd_compress.c (determine_blockSize),
|
||||
* except it doesn't check for a block delimiter to end summation.
|
||||
* Removing the early exit allows the compiler to auto-vectorize (https://godbolt.org/z/cY1cajz9P).
|
||||
* This function can be deleted and replaced by determine_blockSize after we resolve issue #3456. */
|
||||
static size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seqBufSize) {
|
||||
size_t matchLenSum, litLenSum, i;
|
||||
matchLenSum = 0;
|
||||
litLenSum = 0;
|
||||
for (i = 0; i < seqBufSize; i++) {
|
||||
litLenSum += seqBuf[i].litLength;
|
||||
matchLenSum += seqBuf[i].matchLength;
|
||||
}
|
||||
return litLenSum + matchLenSum;
|
||||
}
|
||||
|
||||
typedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_buildSeqStore_e;
|
||||
|
||||
static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
@@ -2904,6 +3135,15 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
}
|
||||
if (zc->externSeqStore.pos < zc->externSeqStore.size) {
|
||||
assert(zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_disable);
|
||||
|
||||
/* External matchfinder + LDM is technically possible, just not implemented yet.
|
||||
* We need to revisit soon and implement it. */
|
||||
RETURN_ERROR_IF(
|
||||
zc->appliedParams.useExternalMatchFinder,
|
||||
parameter_combination_unsupported,
|
||||
"Long-distance matching with external matchfinder enabled is not currently supported."
|
||||
);
|
||||
|
||||
/* Updates ldmSeqStore.pos */
|
||||
lastLLSize =
|
||||
ZSTD_ldm_blockCompress(&zc->externSeqStore,
|
||||
@@ -2915,6 +3155,14 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
} else if (zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {
|
||||
rawSeqStore_t ldmSeqStore = kNullRawSeqStore;
|
||||
|
||||
/* External matchfinder + LDM is technically possible, just not implemented yet.
|
||||
* We need to revisit soon and implement it. */
|
||||
RETURN_ERROR_IF(
|
||||
zc->appliedParams.useExternalMatchFinder,
|
||||
parameter_combination_unsupported,
|
||||
"Long-distance matching with external matchfinder enabled is not currently supported."
|
||||
);
|
||||
|
||||
ldmSeqStore.seq = zc->ldmSequences;
|
||||
ldmSeqStore.capacity = zc->maxNbLdmSequences;
|
||||
/* Updates ldmSeqStore.size */
|
||||
@@ -2929,7 +3177,68 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
|
||||
zc->appliedParams.useRowMatchFinder,
|
||||
src, srcSize);
|
||||
assert(ldmSeqStore.pos == ldmSeqStore.size);
|
||||
} else { /* not long range mode */
|
||||
} else if (zc->appliedParams.useExternalMatchFinder) {
|
||||
assert(
|
||||
zc->externalMatchCtx.seqBufferCapacity >= ZSTD_sequenceBound(srcSize)
|
||||
);
|
||||
assert(zc->externalMatchCtx.mFinder != NULL);
|
||||
|
||||
{ U32 const windowSize = (U32)1 << zc->appliedParams.cParams.windowLog;
|
||||
|
||||
size_t const nbExternalSeqs = (zc->externalMatchCtx.mFinder)(
|
||||
zc->externalMatchCtx.mState,
|
||||
zc->externalMatchCtx.seqBuffer,
|
||||
zc->externalMatchCtx.seqBufferCapacity,
|
||||
src, srcSize,
|
||||
NULL, 0, /* dict and dictSize, currently not supported */
|
||||
zc->appliedParams.compressionLevel,
|
||||
windowSize
|
||||
);
|
||||
|
||||
size_t const nbPostProcessedSeqs = ZSTD_postProcessExternalMatchFinderResult(
|
||||
zc->externalMatchCtx.seqBuffer,
|
||||
nbExternalSeqs,
|
||||
zc->externalMatchCtx.seqBufferCapacity,
|
||||
srcSize
|
||||
);
|
||||
|
||||
/* Return early if there is no error, since we don't need to worry about last literals */
|
||||
if (!ZSTD_isError(nbPostProcessedSeqs)) {
|
||||
ZSTD_sequencePosition seqPos = {0,0,0};
|
||||
size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->externalMatchCtx.seqBuffer, nbPostProcessedSeqs);
|
||||
RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, "External sequences imply too large a block!");
|
||||
FORWARD_IF_ERROR(
|
||||
ZSTD_copySequencesToSeqStoreExplicitBlockDelim(
|
||||
zc, &seqPos,
|
||||
zc->externalMatchCtx.seqBuffer, nbPostProcessedSeqs,
|
||||
src, srcSize,
|
||||
zc->appliedParams.searchForExternalRepcodes
|
||||
),
|
||||
"Failed to copy external sequences to seqStore!"
|
||||
);
|
||||
ms->ldmSeqStore = NULL;
|
||||
DEBUGLOG(5, "Copied %lu sequences from external matchfinder to internal seqStore.", (unsigned long)nbExternalSeqs);
|
||||
return ZSTDbss_compress;
|
||||
}
|
||||
|
||||
/* Propagate the error if fallback is disabled */
|
||||
if (!zc->appliedParams.enableMatchFinderFallback) {
|
||||
return nbPostProcessedSeqs;
|
||||
}
|
||||
|
||||
/* Fallback to software matchfinder */
|
||||
{ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy,
|
||||
zc->appliedParams.useRowMatchFinder,
|
||||
dictMode);
|
||||
ms->ldmSeqStore = NULL;
|
||||
DEBUGLOG(
|
||||
5,
|
||||
"External matchfinder returned error code %lu. Falling back to internal matchfinder.",
|
||||
(unsigned long)nbExternalSeqs
|
||||
);
|
||||
lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);
|
||||
} }
|
||||
} else { /* not long range mode and no external matchfinder */
|
||||
ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy,
|
||||
zc->appliedParams.useRowMatchFinder,
|
||||
dictMode);
|
||||
@@ -3055,19 +3364,17 @@ static int ZSTD_isRLE(const BYTE* src, size_t length) {
|
||||
const size_t unrollMask = unrollSize - 1;
|
||||
const size_t prefixLength = length & unrollMask;
|
||||
size_t i;
|
||||
size_t u;
|
||||
if (length == 1) return 1;
|
||||
/* Check if prefix is RLE first before using unrolled loop */
|
||||
if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) {
|
||||
return 0;
|
||||
}
|
||||
for (i = prefixLength; i != length; i += unrollSize) {
|
||||
size_t u;
|
||||
for (u = 0; u < unrollSize; u += sizeof(size_t)) {
|
||||
if (MEM_readST(ip + i + u) != valueST) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} } }
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -3083,7 +3390,8 @@ static int ZSTD_maybeRLE(seqStore_t const* seqStore)
|
||||
return nbSeqs < 4 && nbLits < 10;
|
||||
}
|
||||
|
||||
static void ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs)
|
||||
static void
|
||||
ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs)
|
||||
{
|
||||
ZSTD_compressedBlockState_t* const tmp = bs->prevCBlock;
|
||||
bs->prevCBlock = bs->nextCBlock;
|
||||
@@ -3091,7 +3399,9 @@ static void ZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* c
|
||||
}
|
||||
|
||||
/* Writes the block header */
|
||||
static void writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock) {
|
||||
static void
|
||||
writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock)
|
||||
{
|
||||
U32 const cBlockHeader = cSize == 1 ?
|
||||
lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :
|
||||
lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);
|
||||
@@ -3104,13 +3414,16 @@ static void writeBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastB
|
||||
* Stores literals block type (raw, rle, compressed, repeat) and
|
||||
* huffman description table to hufMetadata.
|
||||
* Requires ENTROPY_WORKSPACE_SIZE workspace
|
||||
* @return : size of huffman description table or error code */
|
||||
static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSize,
|
||||
const ZSTD_hufCTables_t* prevHuf,
|
||||
ZSTD_hufCTables_t* nextHuf,
|
||||
ZSTD_hufCTablesMetadata_t* hufMetadata,
|
||||
const int literalsCompressionIsDisabled,
|
||||
void* workspace, size_t wkspSize, HUF_depth_mode depthMode)
|
||||
* @return : size of huffman description table, or an error code
|
||||
*/
|
||||
static size_t
|
||||
ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSize,
|
||||
const ZSTD_hufCTables_t* prevHuf,
|
||||
ZSTD_hufCTables_t* nextHuf,
|
||||
ZSTD_hufCTablesMetadata_t* hufMetadata,
|
||||
const int literalsCompressionIsDisabled,
|
||||
void* workspace, size_t wkspSize,
|
||||
int hufFlags)
|
||||
{
|
||||
BYTE* const wkspStart = (BYTE*)workspace;
|
||||
BYTE* const wkspEnd = wkspStart + wkspSize;
|
||||
@@ -3135,74 +3448,77 @@ static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSi
|
||||
|
||||
/* small ? don't even attempt compression (speed opt) */
|
||||
#ifndef COMPRESS_LITERALS_SIZE_MIN
|
||||
#define COMPRESS_LITERALS_SIZE_MIN 63
|
||||
# define COMPRESS_LITERALS_SIZE_MIN 63 /* heuristic */
|
||||
#endif
|
||||
{ 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);
|
||||
{ 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) {
|
||||
/* only one literal symbol */
|
||||
DEBUGLOG(5, "set_rle");
|
||||
hufMetadata->hType = set_rle;
|
||||
return 0;
|
||||
}
|
||||
if (largest <= (srcSize >> 7)+4) {
|
||||
/* heuristic: likely not compressible */
|
||||
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)) {
|
||||
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, nodeWksp, nodeWkspSize, nextHuf->CTable, countWksp, depthMode);
|
||||
huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, nodeWksp, nodeWkspSize, nextHuf->CTable, countWksp, hufFlags);
|
||||
assert(huffLog <= LitHufLog);
|
||||
{ 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_wksp(
|
||||
hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
|
||||
(HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog,
|
||||
nodeWksp, nodeWkspSize);
|
||||
/* 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");
|
||||
}
|
||||
{ /* Build and write the CTable */
|
||||
size_t const newCSize = HUF_estimateCompressedSize(
|
||||
(HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);
|
||||
size_t const hSize = HUF_writeCTable_wksp(
|
||||
hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),
|
||||
(HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog,
|
||||
nodeWksp, nodeWkspSize);
|
||||
/* 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_basic;
|
||||
hufMetadata->hType = set_repeat;
|
||||
return 0;
|
||||
}
|
||||
DEBUGLOG(5, "set_compressed (hSize=%u)", (U32)hSize);
|
||||
hufMetadata->hType = set_compressed;
|
||||
nextHuf->repeatMode = HUF_repeat_check;
|
||||
return hSize;
|
||||
} }
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3212,8 +3528,9 @@ static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSi
|
||||
* and updates nextEntropy to the appropriate repeatMode.
|
||||
*/
|
||||
static ZSTD_symbolEncodingTypeStats_t
|
||||
ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy) {
|
||||
ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0};
|
||||
ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy)
|
||||
{
|
||||
ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0, 0};
|
||||
nextEntropy->litlength_repeatMode = FSE_repeat_none;
|
||||
nextEntropy->offcode_repeatMode = FSE_repeat_none;
|
||||
nextEntropy->matchlength_repeatMode = FSE_repeat_none;
|
||||
@@ -3224,16 +3541,18 @@ ZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy) {
|
||||
* Builds entropy for the sequences.
|
||||
* Stores symbol compression modes and fse table to fseMetadata.
|
||||
* Requires ENTROPY_WORKSPACE_SIZE wksp.
|
||||
* @return : size of fse tables or error code */
|
||||
static size_t ZSTD_buildBlockEntropyStats_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)
|
||||
* @return : size of fse tables or error code */
|
||||
static size_t
|
||||
ZSTD_buildBlockEntropyStats_sequences(
|
||||
const 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)
|
||||
{
|
||||
ZSTD_strategy const strategy = cctxParams->cParams.strategy;
|
||||
size_t const nbSeq = seqStorePtr->sequences - seqStorePtr->sequencesStart;
|
||||
size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
|
||||
BYTE* const ostart = fseMetadata->fseTablesBuffer;
|
||||
BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);
|
||||
BYTE* op = ostart;
|
||||
@@ -3260,25 +3579,27 @@ static size_t ZSTD_buildBlockEntropyStats_sequences(seqStore_t* seqStorePtr,
|
||||
/** ZSTD_buildBlockEntropyStats() :
|
||||
* Builds entropy for the block.
|
||||
* Requires workspace size ENTROPY_WORKSPACE_SIZE
|
||||
*
|
||||
* @return : 0 on success or error code
|
||||
* @return : 0 on success, or an error code
|
||||
* Note : also employed in superblock
|
||||
*/
|
||||
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)
|
||||
size_t ZSTD_buildBlockEntropyStats(
|
||||
const 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;
|
||||
HUF_depth_mode depthMode = cctxParams->cParams.strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD ? HUF_depth_optimal : HUF_depth_fast;
|
||||
size_t const litSize = (size_t)(seqStorePtr->lit - seqStorePtr->litStart);
|
||||
int const huf_useOptDepth = (cctxParams->cParams.strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD);
|
||||
int const hufFlags = huf_useOptDepth ? HUF_flags_optimalDepth : 0;
|
||||
|
||||
entropyMetadata->hufMetadata.hufDesSize =
|
||||
ZSTD_buildBlockEntropyStats_literals(seqStorePtr->litStart, litSize,
|
||||
&prevEntropy->huf, &nextEntropy->huf,
|
||||
&entropyMetadata->hufMetadata,
|
||||
ZSTD_literalsCompressionIsDisabled(cctxParams),
|
||||
workspace, wkspSize, depthMode);
|
||||
workspace, wkspSize, hufFlags);
|
||||
|
||||
FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildBlockEntropyStats_literals failed");
|
||||
entropyMetadata->fseMetadata.fseTablesSize =
|
||||
@@ -3292,11 +3613,12 @@ size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
|
||||
}
|
||||
|
||||
/* Returns the size estimate for the literals section (header + content) of a block */
|
||||
static size_t ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize,
|
||||
const ZSTD_hufCTables_t* huf,
|
||||
const ZSTD_hufCTablesMetadata_t* hufMetadata,
|
||||
void* workspace, size_t wkspSize,
|
||||
int writeEntropy)
|
||||
static size_t
|
||||
ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize,
|
||||
const ZSTD_hufCTables_t* huf,
|
||||
const ZSTD_hufCTablesMetadata_t* hufMetadata,
|
||||
void* workspace, size_t wkspSize,
|
||||
int writeEntropy)
|
||||
{
|
||||
unsigned* const countWksp = (unsigned*)workspace;
|
||||
unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX;
|
||||
@@ -3318,12 +3640,13 @@ static size_t ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSiz
|
||||
}
|
||||
|
||||
/* Returns the size estimate for the FSE-compressed symbols (of, ml, ll) of a block */
|
||||
static size_t ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type,
|
||||
const BYTE* codeTable, size_t nbSeq, unsigned maxCode,
|
||||
const FSE_CTable* fseCTable,
|
||||
const U8* additionalBits,
|
||||
short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
|
||||
void* workspace, size_t wkspSize)
|
||||
static size_t
|
||||
ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type,
|
||||
const BYTE* codeTable, size_t nbSeq, unsigned maxCode,
|
||||
const FSE_CTable* fseCTable,
|
||||
const U8* additionalBits,
|
||||
short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
|
||||
void* workspace, size_t wkspSize)
|
||||
{
|
||||
unsigned* const countWksp = (unsigned*)workspace;
|
||||
const BYTE* ctp = codeTable;
|
||||
@@ -3355,99 +3678,107 @@ static size_t ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type,
|
||||
}
|
||||
|
||||
/* Returns the size estimate for the sequences section (header + content) of a block */
|
||||
static size_t ZSTD_estimateBlockSize_sequences(const BYTE* ofCodeTable,
|
||||
const BYTE* llCodeTable,
|
||||
const BYTE* mlCodeTable,
|
||||
size_t nbSeq,
|
||||
const ZSTD_fseCTables_t* fseTables,
|
||||
const ZSTD_fseCTablesMetadata_t* fseMetadata,
|
||||
void* workspace, size_t wkspSize,
|
||||
int writeEntropy)
|
||||
static size_t
|
||||
ZSTD_estimateBlockSize_sequences(const BYTE* ofCodeTable,
|
||||
const BYTE* llCodeTable,
|
||||
const BYTE* mlCodeTable,
|
||||
size_t nbSeq,
|
||||
const ZSTD_fseCTables_t* fseTables,
|
||||
const ZSTD_fseCTablesMetadata_t* fseMetadata,
|
||||
void* workspace, size_t wkspSize,
|
||||
int writeEntropy)
|
||||
{
|
||||
size_t sequencesSectionHeaderSize = 1 /* seqHead */ + 1 /* min seqSize size */ + (nbSeq >= 128) + (nbSeq >= LONGNBSEQ);
|
||||
size_t cSeqSizeEstimate = 0;
|
||||
cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, nbSeq, MaxOff,
|
||||
fseTables->offcodeCTable, NULL,
|
||||
OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
||||
workspace, wkspSize);
|
||||
fseTables->offcodeCTable, NULL,
|
||||
OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,
|
||||
workspace, wkspSize);
|
||||
cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->llType, llCodeTable, nbSeq, MaxLL,
|
||||
fseTables->litlengthCTable, LL_bits,
|
||||
LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
||||
workspace, wkspSize);
|
||||
fseTables->litlengthCTable, LL_bits,
|
||||
LL_defaultNorm, LL_defaultNormLog, MaxLL,
|
||||
workspace, wkspSize);
|
||||
cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, nbSeq, MaxML,
|
||||
fseTables->matchlengthCTable, ML_bits,
|
||||
ML_defaultNorm, ML_defaultNormLog, MaxML,
|
||||
workspace, wkspSize);
|
||||
fseTables->matchlengthCTable, ML_bits,
|
||||
ML_defaultNorm, ML_defaultNormLog, MaxML,
|
||||
workspace, wkspSize);
|
||||
if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;
|
||||
return cSeqSizeEstimate + sequencesSectionHeaderSize;
|
||||
}
|
||||
|
||||
/* Returns the size estimate for a given stream of literals, of, ll, ml */
|
||||
static size_t ZSTD_estimateBlockSize(const BYTE* literals, size_t litSize,
|
||||
const BYTE* ofCodeTable,
|
||||
const BYTE* llCodeTable,
|
||||
const BYTE* mlCodeTable,
|
||||
size_t nbSeq,
|
||||
const ZSTD_entropyCTables_t* entropy,
|
||||
const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
|
||||
void* workspace, size_t wkspSize,
|
||||
int writeLitEntropy, int writeSeqEntropy) {
|
||||
static size_t
|
||||
ZSTD_estimateBlockSize(const BYTE* literals, size_t litSize,
|
||||
const BYTE* ofCodeTable,
|
||||
const BYTE* llCodeTable,
|
||||
const BYTE* mlCodeTable,
|
||||
size_t nbSeq,
|
||||
const ZSTD_entropyCTables_t* entropy,
|
||||
const ZSTD_entropyCTablesMetadata_t* entropyMetadata,
|
||||
void* workspace, size_t wkspSize,
|
||||
int writeLitEntropy, int writeSeqEntropy)
|
||||
{
|
||||
size_t const literalsSize = ZSTD_estimateBlockSize_literal(literals, litSize,
|
||||
&entropy->huf, &entropyMetadata->hufMetadata,
|
||||
workspace, wkspSize, writeLitEntropy);
|
||||
&entropy->huf, &entropyMetadata->hufMetadata,
|
||||
workspace, wkspSize, writeLitEntropy);
|
||||
size_t const seqSize = ZSTD_estimateBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,
|
||||
nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
|
||||
workspace, wkspSize, writeSeqEntropy);
|
||||
nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,
|
||||
workspace, wkspSize, writeSeqEntropy);
|
||||
return seqSize + literalsSize + ZSTD_blockHeaderSize;
|
||||
}
|
||||
|
||||
/* Builds entropy statistics and uses them for blocksize estimation.
|
||||
*
|
||||
* Returns the estimated compressed size of the seqStore, or a zstd error.
|
||||
* @return: estimated compressed size of the seqStore, or a zstd error.
|
||||
*/
|
||||
static size_t ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CCtx* zc) {
|
||||
ZSTD_entropyCTablesMetadata_t* entropyMetadata = &zc->blockSplitCtx.entropyMetadata;
|
||||
static size_t
|
||||
ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CCtx* zc)
|
||||
{
|
||||
ZSTD_entropyCTablesMetadata_t* const entropyMetadata = &zc->blockSplitCtx.entropyMetadata;
|
||||
DEBUGLOG(6, "ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize()");
|
||||
FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(seqStore,
|
||||
&zc->blockState.prevCBlock->entropy,
|
||||
&zc->blockState.nextCBlock->entropy,
|
||||
&zc->appliedParams,
|
||||
entropyMetadata,
|
||||
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
|
||||
return ZSTD_estimateBlockSize(seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart),
|
||||
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE), "");
|
||||
return ZSTD_estimateBlockSize(
|
||||
seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart),
|
||||
seqStore->ofCode, seqStore->llCode, seqStore->mlCode,
|
||||
(size_t)(seqStore->sequences - seqStore->sequencesStart),
|
||||
&zc->blockState.nextCBlock->entropy, entropyMetadata, zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE,
|
||||
&zc->blockState.nextCBlock->entropy,
|
||||
entropyMetadata,
|
||||
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE,
|
||||
(int)(entropyMetadata->hufMetadata.hType == set_compressed), 1);
|
||||
}
|
||||
|
||||
/* Returns literals bytes represented in a seqStore */
|
||||
static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore) {
|
||||
static size_t ZSTD_countSeqStoreLiteralsBytes(const seqStore_t* const seqStore)
|
||||
{
|
||||
size_t literalsBytes = 0;
|
||||
size_t const nbSeqs = seqStore->sequences - seqStore->sequencesStart;
|
||||
size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);
|
||||
size_t i;
|
||||
for (i = 0; i < nbSeqs; ++i) {
|
||||
seqDef seq = seqStore->sequencesStart[i];
|
||||
seqDef const seq = seqStore->sequencesStart[i];
|
||||
literalsBytes += seq.litLength;
|
||||
if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_literalLength) {
|
||||
literalsBytes += 0x10000;
|
||||
}
|
||||
}
|
||||
} }
|
||||
return literalsBytes;
|
||||
}
|
||||
|
||||
/* Returns match bytes represented in a seqStore */
|
||||
static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) {
|
||||
static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore)
|
||||
{
|
||||
size_t matchBytes = 0;
|
||||
size_t const nbSeqs = seqStore->sequences - seqStore->sequencesStart;
|
||||
size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);
|
||||
size_t i;
|
||||
for (i = 0; i < nbSeqs; ++i) {
|
||||
seqDef seq = seqStore->sequencesStart[i];
|
||||
matchBytes += seq.mlBase + MINMATCH;
|
||||
if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) {
|
||||
matchBytes += 0x10000;
|
||||
}
|
||||
}
|
||||
} }
|
||||
return matchBytes;
|
||||
}
|
||||
|
||||
@@ -3496,6 +3827,7 @@ ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offBase, c
|
||||
U32 const adjustedRepCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0; /* [ 0 - 3 ] */
|
||||
assert(OFFBASE_IS_REPCODE(offBase));
|
||||
if (adjustedRepCode == ZSTD_REP_NUM) {
|
||||
assert(ll0);
|
||||
/* litlength == 0 and offCode == 2 implies selection of first repcode - 1
|
||||
* This is only valid if it results in a valid offset value, aka > 0.
|
||||
* Note : it may happen that `rep[0]==1` in exceptional circumstances.
|
||||
@@ -3521,14 +3853,16 @@ ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offBase, c
|
||||
* 1-3 : repcode 1-3
|
||||
* 4+ : real_offset+3
|
||||
*/
|
||||
static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes,
|
||||
seqStore_t* const seqStore, U32 const nbSeq) {
|
||||
static void
|
||||
ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes,
|
||||
const seqStore_t* const seqStore, U32 const nbSeq)
|
||||
{
|
||||
U32 idx = 0;
|
||||
for (; idx < nbSeq; ++idx) {
|
||||
seqDef* const seq = seqStore->sequencesStart + idx;
|
||||
U32 const ll0 = (seq->litLength == 0);
|
||||
U32 const offBase = seq->offBase;
|
||||
assert(seq->offBase > 0);
|
||||
assert(offBase > 0);
|
||||
if (OFFBASE_IS_REPCODE(offBase)) {
|
||||
U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offBase, ll0);
|
||||
U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offBase, ll0);
|
||||
@@ -3537,7 +3871,7 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
|
||||
* repcode history.
|
||||
*/
|
||||
if (dRawOffset != cRawOffset) {
|
||||
seq->offBase = cRawOffset + ZSTD_REP_NUM;
|
||||
seq->offBase = OFFSET_TO_OFFBASE(cRawOffset);
|
||||
}
|
||||
}
|
||||
/* Compression repcode history is always updated with values directly from the unmodified seqStore.
|
||||
@@ -3554,10 +3888,11 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
|
||||
* Returns the total size of that block (including header) or a ZSTD error code.
|
||||
*/
|
||||
static size_t
|
||||
ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const seqStore,
|
||||
ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc,
|
||||
const seqStore_t* const seqStore,
|
||||
repcodes_t* const dRep, repcodes_t* const cRep,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* src, size_t srcSize,
|
||||
U32 lastBlock, U32 isPartition)
|
||||
{
|
||||
const U32 rleMaxLength = 25;
|
||||
@@ -3631,10 +3966,11 @@ typedef struct {
|
||||
|
||||
/* Helper function to perform the recursive search for block splits.
|
||||
* Estimates the cost of seqStore prior to split, and estimates the cost of splitting the sequences in half.
|
||||
* If advantageous to split, then we recurse down the two sub-blocks. If not, or if an error occurred in estimation, then
|
||||
* we do not recurse.
|
||||
* If advantageous to split, then we recurse down the two sub-blocks.
|
||||
* If not, or if an error occurred in estimation, then we do not recurse.
|
||||
*
|
||||
* Note: The recursion depth is capped by a heuristic minimum number of sequences, defined by MIN_SEQUENCES_BLOCK_SPLITTING.
|
||||
* Note: The recursion depth is capped by a heuristic minimum number of sequences,
|
||||
* defined by MIN_SEQUENCES_BLOCK_SPLITTING.
|
||||
* In theory, this means the absolute largest recursion depth is 10 == log2(maxNbSeqInBlock/MIN_SEQUENCES_BLOCK_SPLITTING).
|
||||
* In practice, recursion depth usually doesn't go beyond 4.
|
||||
*
|
||||
@@ -3646,19 +3982,20 @@ static void
|
||||
ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,
|
||||
ZSTD_CCtx* zc, const seqStore_t* origSeqStore)
|
||||
{
|
||||
seqStore_t* fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk;
|
||||
seqStore_t* firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore;
|
||||
seqStore_t* secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore;
|
||||
seqStore_t* const fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk;
|
||||
seqStore_t* const firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore;
|
||||
seqStore_t* const secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore;
|
||||
size_t estimatedOriginalSize;
|
||||
size_t estimatedFirstHalfSize;
|
||||
size_t estimatedSecondHalfSize;
|
||||
size_t midIdx = (startIdx + endIdx)/2;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_deriveBlockSplitsHelper: startIdx=%zu endIdx=%zu", startIdx, endIdx);
|
||||
assert(endIdx >= startIdx);
|
||||
if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= ZSTD_MAX_NB_BLOCK_SPLITS) {
|
||||
DEBUGLOG(6, "ZSTD_deriveBlockSplitsHelper: Too few sequences");
|
||||
DEBUGLOG(6, "ZSTD_deriveBlockSplitsHelper: Too few sequences (%zu)", endIdx - startIdx);
|
||||
return;
|
||||
}
|
||||
DEBUGLOG(5, "ZSTD_deriveBlockSplitsHelper: startIdx=%zu endIdx=%zu", startIdx, endIdx);
|
||||
ZSTD_deriveSeqStoreChunk(fullSeqStoreChunk, origSeqStore, startIdx, endIdx);
|
||||
ZSTD_deriveSeqStoreChunk(firstHalfSeqStore, origSeqStore, startIdx, midIdx);
|
||||
ZSTD_deriveSeqStoreChunk(secondHalfSeqStore, origSeqStore, midIdx, endIdx);
|
||||
@@ -3679,15 +4016,18 @@ ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t end
|
||||
}
|
||||
}
|
||||
|
||||
/* Base recursive function. Populates a table with intra-block partition indices that can improve compression ratio.
|
||||
/* Base recursive function.
|
||||
* Populates a table with intra-block partition indices that can improve compression ratio.
|
||||
*
|
||||
* Returns the number of splits made (which equals the size of the partition table - 1).
|
||||
* @return: number of splits made (which equals the size of the partition table - 1).
|
||||
*/
|
||||
static size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq)
|
||||
{
|
||||
seqStoreSplits splits = {partitions, 0};
|
||||
seqStoreSplits splits;
|
||||
splits.splitLocations = partitions;
|
||||
splits.idx = 0;
|
||||
if (nbSeq <= 4) {
|
||||
DEBUGLOG(5, "ZSTD_deriveBlockSplits: Too few sequences to split");
|
||||
DEBUGLOG(5, "ZSTD_deriveBlockSplits: Too few sequences to split (%u <= 4)", nbSeq);
|
||||
/* Refuse to try and split anything with less than 4 sequences */
|
||||
return 0;
|
||||
}
|
||||
@@ -3703,18 +4043,20 @@ static size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq)
|
||||
* Returns combined size of all blocks (which includes headers), or a ZSTD error code.
|
||||
*/
|
||||
static size_t
|
||||
ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity,
|
||||
const void* src, size_t blockSize, U32 lastBlock, U32 nbSeq)
|
||||
ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t blockSize,
|
||||
U32 lastBlock, U32 nbSeq)
|
||||
{
|
||||
size_t cSize = 0;
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
size_t i = 0;
|
||||
size_t srcBytesTotal = 0;
|
||||
U32* partitions = zc->blockSplitCtx.partitions; /* size == ZSTD_MAX_NB_BLOCK_SPLITS */
|
||||
seqStore_t* nextSeqStore = &zc->blockSplitCtx.nextSeqStore;
|
||||
seqStore_t* currSeqStore = &zc->blockSplitCtx.currSeqStore;
|
||||
size_t numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq);
|
||||
U32* const partitions = zc->blockSplitCtx.partitions; /* size == ZSTD_MAX_NB_BLOCK_SPLITS */
|
||||
seqStore_t* const nextSeqStore = &zc->blockSplitCtx.nextSeqStore;
|
||||
seqStore_t* const currSeqStore = &zc->blockSplitCtx.currSeqStore;
|
||||
size_t const numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq);
|
||||
|
||||
/* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history
|
||||
* may become invalid. In order to reconcile potentially invalid repcodes, we keep track of two
|
||||
@@ -3736,19 +4078,21 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapac
|
||||
ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
||||
ZSTD_memset(nextSeqStore, 0, sizeof(seqStore_t));
|
||||
|
||||
DEBUGLOG(4, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
|
||||
(unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
|
||||
(unsigned)zc->blockState.matchState.nextToUpdate);
|
||||
|
||||
if (numSplits == 0) {
|
||||
size_t cSizeSingleBlock = ZSTD_compressSeqStore_singleBlock(zc, &zc->seqStore,
|
||||
&dRep, &cRep,
|
||||
op, dstCapacity,
|
||||
ip, blockSize,
|
||||
lastBlock, 0 /* isPartition */);
|
||||
size_t cSizeSingleBlock =
|
||||
ZSTD_compressSeqStore_singleBlock(zc, &zc->seqStore,
|
||||
&dRep, &cRep,
|
||||
op, dstCapacity,
|
||||
ip, blockSize,
|
||||
lastBlock, 0 /* isPartition */);
|
||||
FORWARD_IF_ERROR(cSizeSingleBlock, "Compressing single block from splitBlock_internal() failed!");
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_splitBlock_internal: No splits");
|
||||
assert(cSizeSingleBlock <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize);
|
||||
assert(zc->blockSize <= ZSTD_BLOCKSIZE_MAX);
|
||||
assert(cSizeSingleBlock <= zc->blockSize + ZSTD_blockHeaderSize);
|
||||
return cSizeSingleBlock;
|
||||
}
|
||||
|
||||
@@ -3773,7 +4117,8 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapac
|
||||
op, dstCapacity,
|
||||
ip, srcBytes,
|
||||
lastBlockEntireSrc, 1 /* isPartition */);
|
||||
DEBUGLOG(5, "Estimated size: %zu actual size: %zu", ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(currSeqStore, zc), cSizeChunk);
|
||||
DEBUGLOG(5, "Estimated size: %zu vs %zu : actual size",
|
||||
ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(currSeqStore, zc), cSizeChunk);
|
||||
FORWARD_IF_ERROR(cSizeChunk, "Compressing chunk failed!");
|
||||
|
||||
ip += srcBytes;
|
||||
@@ -3781,10 +4126,10 @@ ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapac
|
||||
dstCapacity -= cSizeChunk;
|
||||
cSize += cSizeChunk;
|
||||
*currSeqStore = *nextSeqStore;
|
||||
assert(cSizeChunk <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize);
|
||||
assert(cSizeChunk <= zc->blockSize + ZSTD_blockHeaderSize);
|
||||
}
|
||||
/* cRep and dRep may have diverged during the compression. If so, we use the dRep repcodes
|
||||
* for the next block.
|
||||
/* cRep and dRep may have diverged during the compression.
|
||||
* If so, we use the dRep repcodes for the next block.
|
||||
*/
|
||||
ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(repcodes_t));
|
||||
return cSize;
|
||||
@@ -3795,8 +4140,6 @@ ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize, U32 lastBlock)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* op = (BYTE*)dst;
|
||||
U32 nbSeq;
|
||||
size_t cSize;
|
||||
DEBUGLOG(4, "ZSTD_compressBlock_splitBlock");
|
||||
@@ -3807,7 +4150,7 @@ ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
|
||||
if (bss == ZSTDbss_noCompress) {
|
||||
if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
|
||||
zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
|
||||
cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock);
|
||||
cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_noCompressBlock failed");
|
||||
DEBUGLOG(4, "ZSTD_compressBlock_splitBlock: Nocompress block");
|
||||
return cSize;
|
||||
@@ -3919,10 +4262,11 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,
|
||||
* * cSize >= blockBound(srcSize): We have expanded the block too much so
|
||||
* emit an uncompressed block.
|
||||
*/
|
||||
{
|
||||
size_t const cSize = ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);
|
||||
{ size_t const cSize =
|
||||
ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);
|
||||
if (cSize != ERROR(dstSize_tooSmall)) {
|
||||
size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);
|
||||
size_t const maxCSize =
|
||||
srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);
|
||||
FORWARD_IF_ERROR(cSize, "ZSTD_compressSuperBlock failed");
|
||||
if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {
|
||||
ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);
|
||||
@@ -3930,7 +4274,7 @@ static size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* if (bss == ZSTDbss_compress)*/
|
||||
|
||||
DEBUGLOG(6, "Resorting to ZSTD_noCompressBlock()");
|
||||
/* Superblock compression failed, attempt to emit a single no compress block.
|
||||
@@ -3988,7 +4332,7 @@ static void ZSTD_overflowCorrectIfNeeded(ZSTD_matchState_t* ms,
|
||||
* All blocks will be terminated, all input will be consumed.
|
||||
* Function will issue an error if there is not enough `dstCapacity` to hold the compressed content.
|
||||
* Frame is supposed already started (header already produced)
|
||||
* @return : compressed size, or an error code
|
||||
* @return : compressed size, or an error code
|
||||
*/
|
||||
static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
@@ -4053,7 +4397,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
|
||||
MEM_writeLE24(op, cBlockHeader);
|
||||
cSize += ZSTD_blockHeaderSize;
|
||||
}
|
||||
}
|
||||
} /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/
|
||||
|
||||
|
||||
ip += blockSize;
|
||||
@@ -4245,7 +4589,7 @@ size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
|
||||
{
|
||||
ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams;
|
||||
assert(!ZSTD_checkCParams(cParams));
|
||||
return MIN (ZSTD_BLOCKSIZE_MAX, (U32)1 << cParams.windowLog);
|
||||
return MIN(cctx->appliedParams.maxBlockSize, (size_t)1 << cParams.windowLog);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
@@ -5682,8 +6026,18 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
|
||||
params.useBlockSplitter = ZSTD_resolveBlockSplitterMode(params.useBlockSplitter, ¶ms.cParams);
|
||||
params.ldmParams.enableLdm = ZSTD_resolveEnableLdm(params.ldmParams.enableLdm, ¶ms.cParams);
|
||||
params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, ¶ms.cParams);
|
||||
params.validateSequences = ZSTD_resolveExternalSequenceValidation(params.validateSequences);
|
||||
params.maxBlockSize = ZSTD_resolveMaxBlockSize(params.maxBlockSize);
|
||||
params.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(params.searchForExternalRepcodes, params.compressionLevel);
|
||||
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
/* If external matchfinder is enabled, make sure to fail before checking job size (for consistency) */
|
||||
RETURN_ERROR_IF(
|
||||
params.useExternalMatchFinder == 1 && params.nbWorkers >= 1,
|
||||
parameter_combination_unsupported,
|
||||
"External matchfinder isn't supported with nbWorkers >= 1"
|
||||
);
|
||||
|
||||
if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {
|
||||
params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */
|
||||
}
|
||||
@@ -5844,13 +6198,20 @@ size_t ZSTD_compressStream2_simpleArgs (
|
||||
const void* src, size_t srcSize, size_t* srcPos,
|
||||
ZSTD_EndDirective endOp)
|
||||
{
|
||||
ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
|
||||
ZSTD_inBuffer input = { src, srcSize, *srcPos };
|
||||
ZSTD_outBuffer output;
|
||||
ZSTD_inBuffer input;
|
||||
output.dst = dst;
|
||||
output.size = dstCapacity;
|
||||
output.pos = *dstPos;
|
||||
input.src = src;
|
||||
input.size = srcSize;
|
||||
input.pos = *srcPos;
|
||||
/* ZSTD_compressStream2() will check validity of dstPos and srcPos */
|
||||
size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp);
|
||||
*dstPos = output.pos;
|
||||
*srcPos = input.pos;
|
||||
return cErr;
|
||||
{ size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp);
|
||||
*dstPos = output.pos;
|
||||
*srcPos = input.pos;
|
||||
return cErr;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
||||
@@ -5873,6 +6234,7 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
||||
/* Reset to the original values. */
|
||||
cctx->requestedParams.inBufferMode = originalInBufferMode;
|
||||
cctx->requestedParams.outBufferMode = originalOutBufferMode;
|
||||
|
||||
FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed");
|
||||
if (result != 0) { /* compression not completed, due to lack of output space */
|
||||
assert(oPos == dstCapacity);
|
||||
@@ -5883,29 +6245,25 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx,
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
U32 idx; /* Index in array of ZSTD_Sequence */
|
||||
U32 posInSequence; /* Position within sequence at idx */
|
||||
size_t posInSrc; /* Number of bytes given by sequences provided so far */
|
||||
} ZSTD_sequencePosition;
|
||||
|
||||
/* ZSTD_validateSequence() :
|
||||
* @offCode : is presumed to follow format required by ZSTD_storeSeq()
|
||||
* @returns a ZSTD error code if sequence is not valid
|
||||
*/
|
||||
static size_t
|
||||
ZSTD_validateSequence(U32 offCode, U32 matchLength,
|
||||
size_t posInSrc, U32 windowLog, size_t dictSize)
|
||||
ZSTD_validateSequence(U32 offCode, U32 matchLength, U32 minMatch,
|
||||
size_t posInSrc, U32 windowLog, size_t dictSize, int useExternalMatchFinder)
|
||||
{
|
||||
U32 const windowSize = 1 << windowLog;
|
||||
U32 const windowSize = 1u << windowLog;
|
||||
/* posInSrc represents the amount of data the decoder would decode up to this point.
|
||||
* As long as the amount of data decoded is less than or equal to window size, offsets may be
|
||||
* larger than the total length of output decoded in order to reference the dict, even larger than
|
||||
* window size. After output surpasses windowSize, we're limited to windowSize offsets again.
|
||||
*/
|
||||
size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
|
||||
RETURN_ERROR_IF(offCode > OFFSET_TO_OFFBASE(offsetBound), corruption_detected, "Offset too large!");
|
||||
RETURN_ERROR_IF(matchLength < MINMATCH, corruption_detected, "Matchlength too small");
|
||||
size_t const matchLenLowerBound = (minMatch == 3 || useExternalMatchFinder) ? 3 : 4;
|
||||
RETURN_ERROR_IF(offCode > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, "Offset too large!");
|
||||
/* Validate maxNbSeq is large enough for the given matchLength and minMatch */
|
||||
RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, "Matchlength too small for the minMatch");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5926,16 +6284,15 @@ static U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32
|
||||
return offBase;
|
||||
}
|
||||
|
||||
/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
|
||||
* ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
|
||||
*/
|
||||
static size_t
|
||||
size_t
|
||||
ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
|
||||
ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize)
|
||||
const void* src, size_t blockSize,
|
||||
ZSTD_paramSwitch_e externalRepSearch)
|
||||
{
|
||||
U32 idx = seqPos->idx;
|
||||
U32 const startIdx = idx;
|
||||
BYTE const* ip = (BYTE const*)(src);
|
||||
const BYTE* const iend = ip + blockSize;
|
||||
repcodes_t updatedRepcodes;
|
||||
@@ -5953,23 +6310,53 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
|
||||
ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
|
||||
for (; idx < inSeqsSize && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) {
|
||||
U32 const litLength = inSeqs[idx].litLength;
|
||||
U32 const ll0 = (litLength == 0);
|
||||
U32 const matchLength = inSeqs[idx].matchLength;
|
||||
U32 const offBase = ZSTD_finalizeOffBase(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
|
||||
ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);
|
||||
U32 offBase;
|
||||
|
||||
if (externalRepSearch == ZSTD_ps_disable) {
|
||||
offBase = OFFSET_TO_OFFBASE(inSeqs[idx].offset);
|
||||
} else {
|
||||
U32 const ll0 = (litLength == 0);
|
||||
offBase = ZSTD_finalizeOffBase(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
|
||||
ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);
|
||||
}
|
||||
|
||||
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength);
|
||||
if (cctx->appliedParams.validateSequences) {
|
||||
seqPos->posInSrc += litLength + matchLength;
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize),
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useExternalMatchFinder),
|
||||
"Sequence validation failed");
|
||||
}
|
||||
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
|
||||
RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,
|
||||
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
|
||||
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength);
|
||||
ip += matchLength + litLength;
|
||||
}
|
||||
|
||||
/* If we skipped repcode search while parsing, we need to update repcodes now */
|
||||
assert(externalRepSearch != ZSTD_ps_auto);
|
||||
assert(idx >= startIdx);
|
||||
if (externalRepSearch == ZSTD_ps_disable && idx != startIdx) {
|
||||
U32* const rep = updatedRepcodes.rep;
|
||||
U32 lastSeqIdx = idx - 1; /* index of last non-block-delimiter sequence */
|
||||
|
||||
if (lastSeqIdx >= startIdx + 2) {
|
||||
rep[2] = inSeqs[lastSeqIdx - 2].offset;
|
||||
rep[1] = inSeqs[lastSeqIdx - 1].offset;
|
||||
rep[0] = inSeqs[lastSeqIdx].offset;
|
||||
} else if (lastSeqIdx == startIdx + 1) {
|
||||
rep[2] = rep[0];
|
||||
rep[1] = inSeqs[lastSeqIdx - 1].offset;
|
||||
rep[0] = inSeqs[lastSeqIdx].offset;
|
||||
} else {
|
||||
assert(lastSeqIdx == startIdx);
|
||||
rep[2] = rep[1];
|
||||
rep[1] = rep[0];
|
||||
rep[0] = inSeqs[lastSeqIdx].offset;
|
||||
}
|
||||
}
|
||||
|
||||
ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
|
||||
|
||||
if (inSeqs[idx].litLength) {
|
||||
@@ -5978,27 +6365,15 @@ ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
|
||||
ip += inSeqs[idx].litLength;
|
||||
seqPos->posInSrc += inSeqs[idx].litLength;
|
||||
}
|
||||
RETURN_ERROR_IF(ip != iend, corruption_detected, "Blocksize doesn't agree with block delimiter!");
|
||||
RETURN_ERROR_IF(ip != iend, externalSequences_invalid, "Blocksize doesn't agree with block delimiter!");
|
||||
seqPos->idx = idx+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the number of bytes to move the current read position back by.
|
||||
* Only non-zero if we ended up splitting a sequence.
|
||||
* Otherwise, it may return a ZSTD error if something went wrong.
|
||||
*
|
||||
* This function will attempt to scan through blockSize bytes
|
||||
* represented by the sequences in @inSeqs,
|
||||
* storing any (partial) sequences.
|
||||
*
|
||||
* Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to
|
||||
* avoid splitting a match, or to avoid splitting a match such that it would produce a match
|
||||
* smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
|
||||
*/
|
||||
static size_t
|
||||
size_t
|
||||
ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize)
|
||||
const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch)
|
||||
{
|
||||
U32 idx = seqPos->idx;
|
||||
U32 startPosInSequence = seqPos->posInSequence;
|
||||
@@ -6010,6 +6385,9 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
|
||||
U32 bytesAdjustment = 0;
|
||||
U32 finalMatchSplit = 0;
|
||||
|
||||
/* TODO(embg) support fast parsing mode in noBlockDelim mode */
|
||||
(void)externalRepSearch;
|
||||
|
||||
if (cctx->cdict) {
|
||||
dictSize = cctx->cdict->dictContentSize;
|
||||
} else if (cctx->prefixDict.dict) {
|
||||
@@ -6039,7 +6417,6 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
|
||||
/* Move to the next sequence */
|
||||
endPosInSequence -= currSeq.litLength + currSeq.matchLength;
|
||||
startPosInSequence = 0;
|
||||
idx++;
|
||||
} else {
|
||||
/* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence
|
||||
does not reach the end of the match. So, we have to split the sequence */
|
||||
@@ -6085,15 +6462,17 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
|
||||
|
||||
if (cctx->appliedParams.validateSequences) {
|
||||
seqPos->posInSrc += litLength + matchLength;
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize),
|
||||
FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,
|
||||
cctx->appliedParams.cParams.windowLog, dictSize, cctx->appliedParams.useExternalMatchFinder),
|
||||
"Sequence validation failed");
|
||||
}
|
||||
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offBase, matchLength, litLength);
|
||||
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
|
||||
RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,
|
||||
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
|
||||
ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength);
|
||||
ip += matchLength + litLength;
|
||||
if (!finalMatchSplit)
|
||||
idx++; /* Next Sequence */
|
||||
}
|
||||
DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
|
||||
assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength);
|
||||
@@ -6116,7 +6495,7 @@ ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition*
|
||||
|
||||
typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize);
|
||||
const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch);
|
||||
static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode)
|
||||
{
|
||||
ZSTD_sequenceCopier sequenceCopier = NULL;
|
||||
@@ -6147,13 +6526,13 @@ blockSize_explicitDelimiter(const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD
|
||||
blockSize += inSeqs[spos].litLength + inSeqs[spos].matchLength;
|
||||
if (end) {
|
||||
if (inSeqs[spos].matchLength != 0)
|
||||
RETURN_ERROR(corruption_detected, "delimiter format error : both matchlength and offset must be == 0");
|
||||
RETURN_ERROR(externalSequences_invalid, "delimiter format error : both matchlength and offset must be == 0");
|
||||
break;
|
||||
}
|
||||
spos++;
|
||||
}
|
||||
if (!end)
|
||||
RETURN_ERROR(corruption_detected, "Reached end of sequences without finding a block delimiter");
|
||||
RETURN_ERROR(externalSequences_invalid, "Reached end of sequences without finding a block delimiter");
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
@@ -6174,9 +6553,9 @@ static size_t determine_blockSize(ZSTD_sequenceFormat_e mode,
|
||||
{ size_t const explicitBlockSize = blockSize_explicitDelimiter(inSeqs, inSeqsSize, seqPos);
|
||||
FORWARD_IF_ERROR(explicitBlockSize, "Error while determining block size with explicit delimiters");
|
||||
if (explicitBlockSize > blockSize)
|
||||
RETURN_ERROR(corruption_detected, "sequences incorrectly define a too large block");
|
||||
RETURN_ERROR(externalSequences_invalid, "sequences incorrectly define a too large block");
|
||||
if (explicitBlockSize > remaining)
|
||||
RETURN_ERROR(srcSize_wrong, "sequences define a frame longer than source");
|
||||
RETURN_ERROR(externalSequences_invalid, "sequences define a frame longer than source");
|
||||
return explicitBlockSize;
|
||||
}
|
||||
}
|
||||
@@ -6224,7 +6603,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
|
||||
ZSTD_resetSeqStore(&cctx->seqStore);
|
||||
DEBUGLOG(5, "Working on new block. Blocksize: %zu (total:%zu)", blockSize, (ip - (const BYTE*)src) + blockSize);
|
||||
|
||||
additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize);
|
||||
additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize, cctx->appliedParams.searchForExternalRepcodes);
|
||||
FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy");
|
||||
blockSize -= additionalByteAdjustment;
|
||||
|
||||
@@ -6256,7 +6635,7 @@ ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
|
||||
|
||||
if (!cctx->isFirstBlock &&
|
||||
ZSTD_maybeRLE(&cctx->seqStore) &&
|
||||
ZSTD_isRLE((BYTE const*)src, srcSize)) {
|
||||
ZSTD_isRLE(ip, blockSize)) {
|
||||
/* We don't want to emit our first block as a RLE even if it qualifies because
|
||||
* doing so will cause the decoder (cli only) to throw a "should consume all input error."
|
||||
* This is only an issue for zstd <= v1.4.3
|
||||
@@ -6493,7 +6872,7 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel,
|
||||
cp.targetLength = (unsigned)(-clampedCompressionLevel);
|
||||
}
|
||||
/* refine parameters based on srcSize & dictSize */
|
||||
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode);
|
||||
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode, ZSTD_ps_auto);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6528,3 +6907,21 @@ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeH
|
||||
if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;
|
||||
return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);
|
||||
}
|
||||
|
||||
void ZSTD_registerExternalMatchFinder(
|
||||
ZSTD_CCtx* zc, void* mState,
|
||||
ZSTD_externalMatchFinder_F* mFinder
|
||||
) {
|
||||
if (mFinder != NULL) {
|
||||
ZSTD_externalMatchCtx emctx;
|
||||
emctx.mState = mState;
|
||||
emctx.mFinder = mFinder;
|
||||
emctx.seqBuffer = NULL;
|
||||
emctx.seqBufferCapacity = 0;
|
||||
zc->externalMatchCtx = emctx;
|
||||
zc->requestedParams.useExternalMatchFinder = 1;
|
||||
} else {
|
||||
ZSTD_memset(&zc->externalMatchCtx, 0, sizeof(zc->externalMatchCtx));
|
||||
zc->requestedParams.useExternalMatchFinder = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -118,12 +118,13 @@ typedef struct {
|
||||
/** 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);
|
||||
size_t ZSTD_buildBlockEntropyStats(
|
||||
const 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 *
|
||||
@@ -149,6 +150,12 @@ typedef struct {
|
||||
size_t capacity; /* The capacity starting from `seq` pointer */
|
||||
} rawSeqStore_t;
|
||||
|
||||
typedef struct {
|
||||
U32 idx; /* Index in array of ZSTD_Sequence */
|
||||
U32 posInSequence; /* Position within sequence at idx */
|
||||
size_t posInSrc; /* Number of bytes given by sequences provided so far */
|
||||
} ZSTD_sequencePosition;
|
||||
|
||||
UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};
|
||||
|
||||
typedef struct {
|
||||
@@ -339,6 +346,21 @@ struct ZSTD_CCtx_params_s {
|
||||
|
||||
/* Controls prefetching in some dictMatchState matchfinders */
|
||||
ZSTD_paramSwitch_e prefetchCDictTables;
|
||||
|
||||
/* Controls whether zstd will fall back to an internal matchfinder
|
||||
* if the external matchfinder returns an error code. */
|
||||
int enableMatchFinderFallback;
|
||||
|
||||
/* Indicates whether an external matchfinder has been referenced.
|
||||
* Users can't set this externally.
|
||||
* It is set internally in ZSTD_registerExternalMatchFinder(). */
|
||||
int useExternalMatchFinder;
|
||||
|
||||
/* Adjust the max block size*/
|
||||
size_t maxBlockSize;
|
||||
|
||||
/* Controls repcode search in external sequence parsing */
|
||||
ZSTD_paramSwitch_e searchForExternalRepcodes;
|
||||
}; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */
|
||||
|
||||
#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))
|
||||
@@ -370,6 +392,14 @@ typedef struct {
|
||||
ZSTD_entropyCTablesMetadata_t entropyMetadata;
|
||||
} ZSTD_blockSplitCtx;
|
||||
|
||||
/* Context for block-level external matchfinder API */
|
||||
typedef struct {
|
||||
void* mState;
|
||||
ZSTD_externalMatchFinder_F* mFinder;
|
||||
ZSTD_Sequence* seqBuffer;
|
||||
size_t seqBufferCapacity;
|
||||
} ZSTD_externalMatchCtx;
|
||||
|
||||
struct ZSTD_CCtx_s {
|
||||
ZSTD_compressionStage_e stage;
|
||||
int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
|
||||
@@ -439,6 +469,9 @@ struct ZSTD_CCtx_s {
|
||||
|
||||
/* Workspace for block splitter */
|
||||
ZSTD_blockSplitCtx blockSplitCtx;
|
||||
|
||||
/* Workspace for external matchfinder */
|
||||
ZSTD_externalMatchCtx externalMatchCtx;
|
||||
};
|
||||
|
||||
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
|
||||
@@ -464,7 +497,7 @@ typedef enum {
|
||||
* In this mode we take both the source size and the dictionary size
|
||||
* into account when selecting and adjusting the parameters.
|
||||
*/
|
||||
ZSTD_cpm_unknown = 3, /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.
|
||||
ZSTD_cpm_unknown = 3 /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.
|
||||
* We don't know what these parameters are for. We default to the legacy
|
||||
* behavior of taking both the source size and the dict size into account
|
||||
* when selecting and adjusting parameters.
|
||||
@@ -555,7 +588,7 @@ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
|
||||
{
|
||||
U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;
|
||||
ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);
|
||||
assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, strat));
|
||||
assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat));
|
||||
return (srcSize >> minlog) + 2;
|
||||
}
|
||||
|
||||
@@ -1142,10 +1175,15 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window,
|
||||
(unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);
|
||||
assert(blockEndIdx >= loadedDictEnd);
|
||||
|
||||
if (blockEndIdx > loadedDictEnd + maxDist) {
|
||||
if (blockEndIdx > loadedDictEnd + maxDist || loadedDictEnd != window->dictLimit) {
|
||||
/* On reaching window size, dictionaries are invalidated.
|
||||
* For simplification, if window size is reached anywhere within next block,
|
||||
* the dictionary is invalidated for the full block.
|
||||
*
|
||||
* We also have to invalidate the dictionary if ZSTD_window_update() has detected
|
||||
* non-contiguous segments, which means that loadedDictEnd != window->dictLimit.
|
||||
* loadedDictEnd may be 0, if forceWindow is true, but in that case we never use
|
||||
* dictMatchState, so setting it to NULL is not a problem.
|
||||
*/
|
||||
DEBUGLOG(6, "invalidating dictionary for current block (distance > windowSize)");
|
||||
*loadedDictEndPtr = 0;
|
||||
@@ -1410,4 +1448,31 @@ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);
|
||||
*/
|
||||
void ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);
|
||||
|
||||
/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
|
||||
* ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
|
||||
* Note that the block delimiter must include the last literals of the block.
|
||||
*/
|
||||
size_t
|
||||
ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
|
||||
ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch);
|
||||
|
||||
/* Returns the number of bytes to move the current read position back by.
|
||||
* Only non-zero if we ended up splitting a sequence.
|
||||
* Otherwise, it may return a ZSTD error if something went wrong.
|
||||
*
|
||||
* This function will attempt to scan through blockSize bytes
|
||||
* represented by the sequences in @inSeqs,
|
||||
* storing any (partial) sequences.
|
||||
*
|
||||
* Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to
|
||||
* avoid splitting a match, or to avoid splitting a match such that it would produce a match
|
||||
* smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
|
||||
*/
|
||||
size_t
|
||||
ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
|
||||
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
|
||||
const void* src, size_t blockSize, ZSTD_paramSwitch_e externalRepSearch);
|
||||
|
||||
#endif /* ZSTD_COMPRESS_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -24,9 +24,9 @@ static size_t showHexa(const void* src, size_t srcSize)
|
||||
const BYTE* const ip = (const BYTE*)src;
|
||||
size_t u;
|
||||
for (u=0; u<srcSize; u++) {
|
||||
RAWLOG(6, " %02X", ip[u]); (void)ip;
|
||||
RAWLOG(5, " %02X", ip[u]); (void)ip;
|
||||
}
|
||||
RAWLOG(6, " \n");
|
||||
RAWLOG(5, " \n");
|
||||
return srcSize;
|
||||
}
|
||||
|
||||
@@ -65,12 +65,26 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src,
|
||||
return srcSize + flSize;
|
||||
}
|
||||
|
||||
static int allBytesIdentical(const void* src, size_t srcSize)
|
||||
{
|
||||
assert(srcSize >= 1);
|
||||
assert(src != NULL);
|
||||
{ const BYTE b = ((const BYTE*)src)[0];
|
||||
size_t p;
|
||||
for (p=1; p<srcSize; p++) {
|
||||
if (((const BYTE*)src)[p] != b) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
U32 const flSize = 1 + (srcSize>31) + (srcSize>4095);
|
||||
|
||||
(void)dstCapacity; /* dstCapacity already guaranteed to be >=4, hence large enough */
|
||||
assert(dstCapacity >= 4); (void)dstCapacity;
|
||||
assert(allBytesIdentical(src, srcSize));
|
||||
|
||||
switch(flSize)
|
||||
{
|
||||
@@ -88,20 +102,41 @@ size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void*
|
||||
}
|
||||
|
||||
ostart[flSize] = *(const BYTE*)src;
|
||||
DEBUGLOG(5, "RLE literals: %u -> %u", (U32)srcSize, (U32)flSize + 1);
|
||||
DEBUGLOG(5, "RLE : Repeated Literal (%02X: %u times) -> %u bytes encoded", ((const BYTE*)src)[0], (U32)srcSize, (U32)flSize + 1);
|
||||
return flSize+1;
|
||||
}
|
||||
|
||||
size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
ZSTD_hufCTables_t* nextHuf,
|
||||
ZSTD_strategy strategy, int disableLiteralCompression,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
void* entropyWorkspace, size_t entropyWorkspaceSize,
|
||||
const int bmi2,
|
||||
unsigned suspectUncompressible, HUF_depth_mode depthMode)
|
||||
/* ZSTD_minLiteralsToCompress() :
|
||||
* returns minimal amount of literals
|
||||
* for literal compression to even be attempted.
|
||||
* Minimum is made tighter as compression strategy increases.
|
||||
*/
|
||||
static size_t
|
||||
ZSTD_minLiteralsToCompress(ZSTD_strategy strategy, HUF_repeat huf_repeat)
|
||||
{
|
||||
assert((int)strategy >= 0);
|
||||
assert((int)strategy <= 9);
|
||||
/* btultra2 : min 8 bytes;
|
||||
* then 2x larger for each successive compression strategy
|
||||
* max threshold 64 bytes */
|
||||
{ int const shift = MIN(9-(int)strategy, 3);
|
||||
size_t const mintc = (huf_repeat == HUF_repeat_valid) ? 6 : (size_t)8 << shift;
|
||||
DEBUGLOG(7, "minLiteralsToCompress = %zu", mintc);
|
||||
return mintc;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ZSTD_compressLiterals (
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
void* entropyWorkspace, size_t entropyWorkspaceSize,
|
||||
const ZSTD_hufCTables_t* prevHuf,
|
||||
ZSTD_hufCTables_t* nextHuf,
|
||||
ZSTD_strategy strategy,
|
||||
int disableLiteralCompression,
|
||||
int suspectUncompressible,
|
||||
int bmi2)
|
||||
{
|
||||
size_t const minGain = ZSTD_minGain(srcSize, strategy);
|
||||
size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
U32 singleStream = srcSize < 256;
|
||||
@@ -119,16 +154,19 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
if (disableLiteralCompression)
|
||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
|
||||
/* 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) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
/* if too small, don't even attempt compression (speed opt) */
|
||||
if (srcSize < ZSTD_minLiteralsToCompress(strategy, prevHuf->repeatMode))
|
||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
|
||||
RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, "not enough space for compression");
|
||||
{ HUF_repeat repeat = prevHuf->repeatMode;
|
||||
int const preferRepeat = (strategy < ZSTD_lazy) ? srcSize <= 1024 : 0;
|
||||
typedef size_t (*huf_compress_f)(void*, size_t, const void*, size_t, unsigned, unsigned, void*, size_t, HUF_CElt*, HUF_repeat*, int, int, unsigned, HUF_depth_mode);
|
||||
int const flags = 0
|
||||
| (bmi2 ? HUF_flags_bmi2 : 0)
|
||||
| (strategy < ZSTD_lazy && srcSize <= 1024 ? HUF_flags_preferRepeat : 0)
|
||||
| (strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD ? HUF_flags_optimalDepth : 0)
|
||||
| (suspectUncompressible ? HUF_flags_suspectUncompressible : 0);
|
||||
|
||||
typedef size_t (*huf_compress_f)(void*, size_t, const void*, size_t, unsigned, unsigned, void*, size_t, HUF_CElt*, HUF_repeat*, int);
|
||||
huf_compress_f huf_compress;
|
||||
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
|
||||
huf_compress = singleStream ? HUF_compress1X_repeat : HUF_compress4X_repeat;
|
||||
@@ -137,23 +175,30 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
HUF_SYMBOLVALUE_MAX, LitHufLog,
|
||||
entropyWorkspace, entropyWorkspaceSize,
|
||||
(HUF_CElt*)nextHuf->CTable,
|
||||
&repeat, preferRepeat,
|
||||
bmi2, suspectUncompressible, depthMode);
|
||||
&repeat, flags);
|
||||
DEBUGLOG(5, "%zu literals compressed into %zu bytes (before header)", srcSize, cLitSize);
|
||||
if (repeat != HUF_repeat_none) {
|
||||
/* reused the existing table */
|
||||
DEBUGLOG(5, "Reusing previous huffman table");
|
||||
DEBUGLOG(5, "reusing statistics from previous huffman block");
|
||||
hType = set_repeat;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) {
|
||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
{ size_t const minGain = ZSTD_minGain(srcSize, strategy);
|
||||
if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) {
|
||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
||||
return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
|
||||
} }
|
||||
if (cLitSize==1) {
|
||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
||||
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
/* A return value of 1 signals that the alphabet consists of a single symbol.
|
||||
* However, in some rare circumstances, it could be the compressed size (a single byte).
|
||||
* For that outcome to have a chance to happen, it's necessary that `srcSize < 8`.
|
||||
* (it's also necessary to not generate statistics).
|
||||
* Therefore, in such a case, actively check that all bytes are identical. */
|
||||
if ((srcSize >= 8) || allBytesIdentical(src, srcSize)) {
|
||||
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
|
||||
return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
|
||||
} }
|
||||
|
||||
if (hType == set_compressed) {
|
||||
/* using a newly constructed table */
|
||||
@@ -164,16 +209,19 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
switch(lhSize)
|
||||
{
|
||||
case 3: /* 2 - 2 - 10 - 10 */
|
||||
if (!singleStream) assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);
|
||||
{ U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);
|
||||
MEM_writeLE24(ostart, lhc);
|
||||
break;
|
||||
}
|
||||
case 4: /* 2 - 2 - 14 - 14 */
|
||||
assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);
|
||||
{ U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);
|
||||
MEM_writeLE32(ostart, lhc);
|
||||
break;
|
||||
}
|
||||
case 5: /* 2 - 2 - 18 - 18 */
|
||||
assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);
|
||||
{ U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
|
||||
MEM_writeLE32(ostart, lhc);
|
||||
ostart[4] = (BYTE)(cLitSize >> 10);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -16,16 +16,24 @@
|
||||
|
||||
size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
|
||||
/* ZSTD_compressRleLiteralsBlock() :
|
||||
* Conditions :
|
||||
* - All bytes in @src are identical
|
||||
* - dstCapacity >= 4 */
|
||||
size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
|
||||
/* If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
|
||||
size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
|
||||
ZSTD_hufCTables_t* nextHuf,
|
||||
ZSTD_strategy strategy, int disableLiteralCompression,
|
||||
void* dst, size_t dstCapacity,
|
||||
/* ZSTD_compressLiterals():
|
||||
* @entropyWorkspace: must be aligned on 4-bytes boundaries
|
||||
* @entropyWorkspaceSize : must be >= HUF_WORKSPACE_SIZE
|
||||
* @suspectUncompressible: sampling checks, to potentially skip huffman coding
|
||||
*/
|
||||
size_t ZSTD_compressLiterals (void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
void* entropyWorkspace, size_t entropyWorkspaceSize,
|
||||
const int bmi2,
|
||||
unsigned suspectUncompressible, HUF_depth_mode depthMode);
|
||||
const ZSTD_hufCTables_t* prevHuf,
|
||||
ZSTD_hufCTables_t* nextHuf,
|
||||
ZSTD_strategy strategy, int disableLiteralCompression,
|
||||
int suspectUncompressible,
|
||||
int bmi2);
|
||||
|
||||
#endif /* ZSTD_COMPRESS_LITERALS_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -54,8 +54,6 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
|
||||
symbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat;
|
||||
size_t cLitSize = 0;
|
||||
|
||||
(void)bmi2; /* TODO bmi2... */
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)", litSize, lhSize, writeEntropy);
|
||||
|
||||
*entropyWritten = 0;
|
||||
@@ -77,9 +75,9 @@ ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,
|
||||
DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize);
|
||||
}
|
||||
|
||||
/* TODO bmi2 */
|
||||
{ const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable)
|
||||
: HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable);
|
||||
{ int const flags = bmi2 ? HUF_flags_bmi2 : 0;
|
||||
const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, oend-op, literals, litSize, hufTable, flags)
|
||||
: HUF_compress4X_usingCTable(op, oend-op, literals, litSize, hufTable, flags);
|
||||
op += cSize;
|
||||
cLitSize += cSize;
|
||||
if (cSize == 0 || ERR_isError(cSize)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -348,7 +348,9 @@ ZSTD_cwksp_reserve_internal(ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase
|
||||
if (alloc) {
|
||||
alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
|
||||
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
|
||||
__asan_unpoison_memory_region(alloc, bytes);
|
||||
/* We need to keep the redzone poisoned while unpoisoning the bytes that
|
||||
* are actually allocated. */
|
||||
__asan_unpoison_memory_region(alloc, bytes - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -759,7 +759,6 @@ size_t ZSTD_HcFindBestMatch(
|
||||
***********************************/
|
||||
/* Constants for row-based hash */
|
||||
#define ZSTD_ROW_HASH_TAG_OFFSET 16 /* byte offset of hashes in the match state's tagTable from the beginning of a row */
|
||||
#define ZSTD_ROW_HASH_TAG_BITS 8 /* nb bits to use for the tag */
|
||||
#define ZSTD_ROW_HASH_TAG_MASK ((1u << ZSTD_ROW_HASH_TAG_BITS) - 1)
|
||||
#define ZSTD_ROW_HASH_MAX_ENTRIES 64 /* absolute maximum number of entries per row, for all configurations */
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -25,6 +25,8 @@ extern "C" {
|
||||
*/
|
||||
#define ZSTD_LAZY_DDSS_BUCKET_LOG 2
|
||||
|
||||
#define ZSTD_ROW_HASH_TAG_BITS 8 /* nb bits to use for the tag */
|
||||
|
||||
U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip);
|
||||
void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip);
|
||||
|
||||
@@ -116,7 +118,7 @@ size_t ZSTD_compressBlock_lazy2_extDict_row(
|
||||
size_t ZSTD_compressBlock_btlazy2_extDict(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
|
||||
void const* src, size_t srcSize);
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+68
-47
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -16,7 +16,7 @@
|
||||
#define ZSTD_LITFREQ_ADD 2 /* scaling factor for litFreq, so that frequencies adapt faster to new stats */
|
||||
#define ZSTD_MAX_PRICE (1<<30)
|
||||
|
||||
#define ZSTD_PREDEF_THRESHOLD 1024 /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */
|
||||
#define ZSTD_PREDEF_THRESHOLD 8 /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -26,27 +26,35 @@
|
||||
#if 0 /* approximation at bit level (for tests) */
|
||||
# define BITCOST_ACCURACY 0
|
||||
# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
|
||||
# define WEIGHT(stat, opt) ((void)opt, ZSTD_bitWeight(stat))
|
||||
# define WEIGHT(stat, opt) ((void)(opt), ZSTD_bitWeight(stat))
|
||||
#elif 0 /* fractional bit accuracy (for tests) */
|
||||
# define BITCOST_ACCURACY 8
|
||||
# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
|
||||
# define WEIGHT(stat,opt) ((void)opt, ZSTD_fracWeight(stat))
|
||||
# define WEIGHT(stat,opt) ((void)(opt), ZSTD_fracWeight(stat))
|
||||
#else /* opt==approx, ultra==accurate */
|
||||
# define BITCOST_ACCURACY 8
|
||||
# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
|
||||
# define WEIGHT(stat,opt) (opt ? ZSTD_fracWeight(stat) : ZSTD_bitWeight(stat))
|
||||
# define WEIGHT(stat,opt) ((opt) ? ZSTD_fracWeight(stat) : ZSTD_bitWeight(stat))
|
||||
#endif
|
||||
|
||||
/* ZSTD_bitWeight() :
|
||||
* provide estimated "cost" of a stat in full bits only */
|
||||
MEM_STATIC U32 ZSTD_bitWeight(U32 stat)
|
||||
{
|
||||
return (ZSTD_highbit32(stat+1) * BITCOST_MULTIPLIER);
|
||||
}
|
||||
|
||||
/* ZSTD_fracWeight() :
|
||||
* provide fractional-bit "cost" of a stat,
|
||||
* using linear interpolation approximation */
|
||||
MEM_STATIC U32 ZSTD_fracWeight(U32 rawStat)
|
||||
{
|
||||
U32 const stat = rawStat + 1;
|
||||
U32 const hb = ZSTD_highbit32(stat);
|
||||
U32 const BWeight = hb * BITCOST_MULTIPLIER;
|
||||
/* Fweight was meant for "Fractional weight"
|
||||
* but it's effectively a value between 1 and 2
|
||||
* using fixed point arithmetic */
|
||||
U32 const FWeight = (stat << BITCOST_ACCURACY) >> hb;
|
||||
U32 const weight = BWeight + FWeight;
|
||||
assert(hb + BITCOST_ACCURACY < 31);
|
||||
@@ -57,7 +65,7 @@ MEM_STATIC U32 ZSTD_fracWeight(U32 rawStat)
|
||||
/* debugging function,
|
||||
* @return price in bytes as fractional value
|
||||
* for debug messages only */
|
||||
MEM_STATIC double ZSTD_fCost(U32 price)
|
||||
MEM_STATIC double ZSTD_fCost(int price)
|
||||
{
|
||||
return (double)price / (BITCOST_MULTIPLIER*8);
|
||||
}
|
||||
@@ -88,20 +96,26 @@ static U32 sum_u32(const unsigned table[], size_t nbElts)
|
||||
return total;
|
||||
}
|
||||
|
||||
static U32 ZSTD_downscaleStats(unsigned* table, U32 lastEltIndex, U32 shift)
|
||||
typedef enum { base_0possible=0, base_1guaranteed=1 } base_directive_e;
|
||||
|
||||
static U32
|
||||
ZSTD_downscaleStats(unsigned* table, U32 lastEltIndex, U32 shift, base_directive_e base1)
|
||||
{
|
||||
U32 s, sum=0;
|
||||
DEBUGLOG(5, "ZSTD_downscaleStats (nbElts=%u, shift=%u)", (unsigned)lastEltIndex+1, (unsigned)shift);
|
||||
DEBUGLOG(5, "ZSTD_downscaleStats (nbElts=%u, shift=%u)",
|
||||
(unsigned)lastEltIndex+1, (unsigned)shift );
|
||||
assert(shift < 30);
|
||||
for (s=0; s<lastEltIndex+1; s++) {
|
||||
table[s] = 1 + (table[s] >> shift);
|
||||
sum += table[s];
|
||||
unsigned const base = base1 ? 1 : (table[s]>0);
|
||||
unsigned const newStat = base + (table[s] >> shift);
|
||||
sum += newStat;
|
||||
table[s] = newStat;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ZSTD_scaleStats() :
|
||||
* reduce all elements in table is sum too large
|
||||
* reduce all elt frequencies in table if sum too large
|
||||
* return the resulting sum of elements */
|
||||
static U32 ZSTD_scaleStats(unsigned* table, U32 lastEltIndex, U32 logTarget)
|
||||
{
|
||||
@@ -110,7 +124,7 @@ static U32 ZSTD_scaleStats(unsigned* table, U32 lastEltIndex, U32 logTarget)
|
||||
DEBUGLOG(5, "ZSTD_scaleStats (nbElts=%u, target=%u)", (unsigned)lastEltIndex+1, (unsigned)logTarget);
|
||||
assert(logTarget < 30);
|
||||
if (factor <= 1) return prevsum;
|
||||
return ZSTD_downscaleStats(table, lastEltIndex, ZSTD_highbit32(factor));
|
||||
return ZSTD_downscaleStats(table, lastEltIndex, ZSTD_highbit32(factor), base_1guaranteed);
|
||||
}
|
||||
|
||||
/* ZSTD_rescaleFreqs() :
|
||||
@@ -129,18 +143,22 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
DEBUGLOG(5, "ZSTD_rescaleFreqs (srcSize=%u)", (unsigned)srcSize);
|
||||
optPtr->priceType = zop_dynamic;
|
||||
|
||||
if (optPtr->litLengthSum == 0) { /* first block : init */
|
||||
if (srcSize <= ZSTD_PREDEF_THRESHOLD) { /* heuristic */
|
||||
DEBUGLOG(5, "(srcSize <= ZSTD_PREDEF_THRESHOLD) => zop_predef");
|
||||
if (optPtr->litLengthSum == 0) { /* no literals stats collected -> first block assumed -> init */
|
||||
|
||||
/* heuristic: use pre-defined stats for too small inputs */
|
||||
if (srcSize <= ZSTD_PREDEF_THRESHOLD) {
|
||||
DEBUGLOG(5, "srcSize <= %i : use predefined stats", ZSTD_PREDEF_THRESHOLD);
|
||||
optPtr->priceType = zop_predef;
|
||||
}
|
||||
|
||||
assert(optPtr->symbolCosts != NULL);
|
||||
if (optPtr->symbolCosts->huf.repeatMode == HUF_repeat_valid) {
|
||||
/* huffman table presumed generated by dictionary */
|
||||
|
||||
/* huffman stats covering the full value set : table presumed generated by dictionary */
|
||||
optPtr->priceType = zop_dynamic;
|
||||
|
||||
if (compressedLiterals) {
|
||||
/* generate literals statistics from huffman table */
|
||||
unsigned lit;
|
||||
assert(optPtr->litFreq != NULL);
|
||||
optPtr->litSum = 0;
|
||||
@@ -188,13 +206,14 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
optPtr->offCodeSum += optPtr->offCodeFreq[of];
|
||||
} }
|
||||
|
||||
} else { /* not a dictionary */
|
||||
} else { /* first block, no dictionary */
|
||||
|
||||
assert(optPtr->litFreq != NULL);
|
||||
if (compressedLiterals) {
|
||||
/* base initial cost of literals on direct frequency within src */
|
||||
unsigned lit = MaxLit;
|
||||
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
|
||||
optPtr->litSum = ZSTD_downscaleStats(optPtr->litFreq, MaxLit, 8);
|
||||
optPtr->litSum = ZSTD_downscaleStats(optPtr->litFreq, MaxLit, 8, base_0possible);
|
||||
}
|
||||
|
||||
{ unsigned const baseLLfreqs[MaxLL+1] = {
|
||||
@@ -224,10 +243,9 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
|
||||
optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
} else { /* new block : re-use previous statistics, scaled down */
|
||||
} else { /* new block : scale down accumulated statistics */
|
||||
|
||||
if (compressedLiterals)
|
||||
optPtr->litSum = ZSTD_scaleStats(optPtr->litFreq, MaxLit, 12);
|
||||
@@ -275,10 +293,11 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
|
||||
assert(litLength <= ZSTD_BLOCKSIZE_MAX);
|
||||
if (optPtr->priceType == zop_predef)
|
||||
return WEIGHT(litLength, optLevel);
|
||||
/* We can't compute the litLength price for sizes >= ZSTD_BLOCKSIZE_MAX
|
||||
* because it isn't representable in the zstd format. So instead just
|
||||
* call it 1 bit more than ZSTD_BLOCKSIZE_MAX - 1. In this case the block
|
||||
* would be all literals.
|
||||
|
||||
/* ZSTD_LLcode() can't compute litLength price for sizes >= ZSTD_BLOCKSIZE_MAX
|
||||
* because it isn't representable in the zstd format.
|
||||
* So instead just pretend it would cost 1 bit more than ZSTD_BLOCKSIZE_MAX - 1.
|
||||
* In such a case, the block would be all literals.
|
||||
*/
|
||||
if (litLength == ZSTD_BLOCKSIZE_MAX)
|
||||
return BITCOST_MULTIPLIER + ZSTD_litLengthPrice(ZSTD_BLOCKSIZE_MAX - 1, optPtr, optLevel);
|
||||
@@ -292,7 +311,7 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
|
||||
}
|
||||
|
||||
/* ZSTD_getMatchPrice() :
|
||||
* Provides the cost of the match part (offset + matchLength) of a sequence
|
||||
* Provides the cost of the match part (offset + matchLength) of a sequence.
|
||||
* Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
|
||||
* @offBase : sumtype, representing an offset or a repcode, and using numeric representation of ZSTD_storeSeq()
|
||||
* @optLevel: when <2, favors small offset for decompression speed (improved cache efficiency)
|
||||
@@ -308,8 +327,9 @@ ZSTD_getMatchPrice(U32 const offBase,
|
||||
U32 const mlBase = matchLength - MINMATCH;
|
||||
assert(matchLength >= MINMATCH);
|
||||
|
||||
if (optPtr->priceType == zop_predef) /* fixed scheme, do not use statistics */
|
||||
return WEIGHT(mlBase, optLevel) + ((16 + offCode) * BITCOST_MULTIPLIER);
|
||||
if (optPtr->priceType == zop_predef) /* fixed scheme, does not use statistics */
|
||||
return WEIGHT(mlBase, optLevel)
|
||||
+ ((16 + offCode) * BITCOST_MULTIPLIER); /* emulated offset cost */
|
||||
|
||||
/* dynamic statistics */
|
||||
price = (offCode * BITCOST_MULTIPLIER) + (optPtr->offCodeSumBasePrice - WEIGHT(optPtr->offCodeFreq[offCode], optLevel));
|
||||
@@ -347,7 +367,7 @@ static void ZSTD_updateStats(optState_t* const optPtr,
|
||||
optPtr->litLengthSum++;
|
||||
}
|
||||
|
||||
/* offset code : expected to follow storeSeq() numeric representation */
|
||||
/* offset code : follows storeSeq() numeric representation */
|
||||
{ U32 const offCode = ZSTD_highbit32(offBase);
|
||||
assert(offCode <= MaxOff);
|
||||
optPtr->offCodeFreq[offCode]++;
|
||||
@@ -555,16 +575,17 @@ void ZSTD_updateTree(ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iend) {
|
||||
ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.minMatch, ZSTD_noDict);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE
|
||||
U32 ZSTD_insertBtAndGetAllMatches (
|
||||
ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
|
||||
ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* const ip, const BYTE* const iLimit, const ZSTD_dictMode_e dictMode,
|
||||
const U32 rep[ZSTD_REP_NUM],
|
||||
U32 const ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
|
||||
const U32 lengthToBeat,
|
||||
U32 const mls /* template */)
|
||||
FORCE_INLINE_TEMPLATE U32
|
||||
ZSTD_insertBtAndGetAllMatches (
|
||||
ZSTD_match_t* matches, /* store result (found matches) in this table (presumed large enough) */
|
||||
ZSTD_matchState_t* ms,
|
||||
U32* nextToUpdate3,
|
||||
const BYTE* const ip, const BYTE* const iLimit,
|
||||
const ZSTD_dictMode_e dictMode,
|
||||
const U32 rep[ZSTD_REP_NUM],
|
||||
const U32 ll0, /* tells if associated literal length is 0 or not. This value must be 0 or 1 */
|
||||
const U32 lengthToBeat,
|
||||
const U32 mls /* template */)
|
||||
{
|
||||
const ZSTD_compressionParameters* const cParams = &ms->cParams;
|
||||
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
|
||||
@@ -1131,7 +1152,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
|
||||
U32 const matchPrice = ZSTD_getMatchPrice(offBase, pos, optStatePtr, optLevel);
|
||||
U32 const sequencePrice = literalsPrice + matchPrice;
|
||||
DEBUGLOG(7, "rPos:%u => set initial price : %.2f",
|
||||
pos, ZSTD_fCost(sequencePrice));
|
||||
pos, ZSTD_fCost((int)sequencePrice));
|
||||
opt[pos].mlen = pos;
|
||||
opt[pos].off = offBase;
|
||||
opt[pos].litlen = litlen;
|
||||
@@ -1352,7 +1373,7 @@ size_t ZSTD_compressBlock_btopt(
|
||||
/* ZSTD_initStats_ultra():
|
||||
* make a first compression pass, just to seed stats with more accurate starting values.
|
||||
* only works on first block, with no dictionary and no ldm.
|
||||
* this function cannot error, hence its contract must be respected.
|
||||
* this function cannot error out, its narrow contract must be respected.
|
||||
*/
|
||||
static void
|
||||
ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
@@ -1371,7 +1392,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
|
||||
|
||||
ZSTD_compressBlock_opt2(ms, seqStore, tmpRep, src, srcSize, ZSTD_noDict); /* generate stats into ms->opt*/
|
||||
|
||||
/* invalidate first scan from history */
|
||||
/* invalidate first scan from history, only keep entropy stats */
|
||||
ZSTD_resetSeqStore(seqStore);
|
||||
ms->window.base -= srcSize;
|
||||
ms->window.dictLimit += (U32)srcSize;
|
||||
@@ -1395,20 +1416,20 @@ size_t ZSTD_compressBlock_btultra2(
|
||||
U32 const curr = (U32)((const BYTE*)src - ms->window.base);
|
||||
DEBUGLOG(5, "ZSTD_compressBlock_btultra2 (srcSize=%zu)", srcSize);
|
||||
|
||||
/* 2-pass strategy:
|
||||
/* 2-passes strategy:
|
||||
* this strategy makes a first pass over first block to collect statistics
|
||||
* and seed next round's statistics with it.
|
||||
* After 1st pass, function forgets everything, and starts a new block.
|
||||
* in order to seed next round's statistics with it.
|
||||
* After 1st pass, function forgets history, and starts a new block.
|
||||
* Consequently, this can only work if no data has been previously loaded in tables,
|
||||
* aka, no dictionary, no prefix, no ldm preprocessing.
|
||||
* The compression ratio gain is generally small (~0.5% on first block),
|
||||
* the cost is 2x cpu time on first block. */
|
||||
** the cost is 2x cpu time on first block. */
|
||||
assert(srcSize <= ZSTD_BLOCKSIZE_MAX);
|
||||
if ( (ms->opt.litLengthSum==0) /* first block */
|
||||
&& (seqStore->sequences == seqStore->sequencesStart) /* no ldm */
|
||||
&& (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */
|
||||
&& (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
|
||||
&& (srcSize > ZSTD_PREDEF_THRESHOLD)
|
||||
&& (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */
|
||||
&& (srcSize > ZSTD_PREDEF_THRESHOLD) /* input large enough to not employ default stats */
|
||||
) {
|
||||
ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+431
-440
@@ -1,7 +1,7 @@
|
||||
/* ******************************************************************
|
||||
* huff0 huffman decoder,
|
||||
* part of Finite State Entropy library
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* You can contact the author at :
|
||||
* - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "../common/compiler.h"
|
||||
#include "../common/bitstream.h" /* BIT_* */
|
||||
#include "../common/fse.h" /* to compress headers */
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "../common/huf.h"
|
||||
#include "../common/error_private.h"
|
||||
#include "../common/zstd_internal.h"
|
||||
@@ -44,10 +43,14 @@
|
||||
#error "Cannot force the use of the X1 and X2 decoders at the same time!"
|
||||
#endif
|
||||
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && DYNAMIC_BMI2
|
||||
# define HUF_ASM_X86_64_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE
|
||||
/* When DYNAMIC_BMI2 is enabled, fast decoders are only called when bmi2 is
|
||||
* supported at runtime, so we can add the BMI2 target attribute.
|
||||
* When it is disabled, we will still get BMI2 if it is enabled statically.
|
||||
*/
|
||||
#if DYNAMIC_BMI2
|
||||
# define HUF_FAST_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE
|
||||
#else
|
||||
# define HUF_ASM_X86_64_BMI2_ATTRS
|
||||
# define HUF_FAST_BMI2_ATTRS
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -57,18 +60,12 @@
|
||||
#endif
|
||||
#define HUF_ASM_DECL HUF_EXTERN_C
|
||||
|
||||
#if DYNAMIC_BMI2 || (ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
|
||||
#if DYNAMIC_BMI2
|
||||
# define HUF_NEED_BMI2_FUNCTION 1
|
||||
#else
|
||||
# define HUF_NEED_BMI2_FUNCTION 0
|
||||
#endif
|
||||
|
||||
#if !(ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
|
||||
# define HUF_NEED_DEFAULT_FUNCTION 1
|
||||
#else
|
||||
# define HUF_NEED_DEFAULT_FUNCTION 0
|
||||
#endif
|
||||
|
||||
/* **************************************************************
|
||||
* Error Management
|
||||
****************************************************************/
|
||||
@@ -85,6 +82,11 @@
|
||||
/* **************************************************************
|
||||
* BMI2 Variant Wrappers
|
||||
****************************************************************/
|
||||
typedef size_t (*HUF_DecompressUsingDTableFn)(void *dst, size_t dstSize,
|
||||
const void *cSrc,
|
||||
size_t cSrcSize,
|
||||
const HUF_DTable *DTable);
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
|
||||
#define HUF_DGEN(fn) \
|
||||
@@ -106,9 +108,9 @@
|
||||
} \
|
||||
\
|
||||
static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int flags) \
|
||||
{ \
|
||||
if (bmi2) { \
|
||||
if (flags & HUF_flags_bmi2) { \
|
||||
return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \
|
||||
} \
|
||||
return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \
|
||||
@@ -118,9 +120,9 @@
|
||||
|
||||
#define HUF_DGEN(fn) \
|
||||
static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int flags) \
|
||||
{ \
|
||||
(void)bmi2; \
|
||||
(void)flags; \
|
||||
return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
|
||||
}
|
||||
|
||||
@@ -139,15 +141,28 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
|
||||
return dtd;
|
||||
}
|
||||
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
|
||||
static size_t HUF_initDStream(BYTE const* ip) {
|
||||
static size_t HUF_initFastDStream(BYTE const* ip) {
|
||||
BYTE const lastByte = ip[7];
|
||||
size_t const bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;
|
||||
size_t const value = MEM_readLEST(ip) | 1;
|
||||
assert(bitsConsumed <= 8);
|
||||
assert(sizeof(size_t) == 8);
|
||||
return value << bitsConsumed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The input/output arguments to the Huffman fast decoding loop:
|
||||
*
|
||||
* ip [in/out] - The input pointers, must be updated to reflect what is consumed.
|
||||
* op [in/out] - The output pointers, must be updated to reflect what is written.
|
||||
* bits [in/out] - The bitstream containers, must be updated to reflect the current state.
|
||||
* dt [in] - The decoding table.
|
||||
* ilimit [in] - The input limit, stop when any input pointer is below ilimit.
|
||||
* oend [in] - The end of the output stream. op[3] must not cross oend.
|
||||
* iend [in] - The end of each input stream. ip[i] may cross iend[i],
|
||||
* as long as it is above ilimit, but that indicates corruption.
|
||||
*/
|
||||
typedef struct {
|
||||
BYTE const* ip[4];
|
||||
BYTE* op[4];
|
||||
@@ -156,15 +171,17 @@ typedef struct {
|
||||
BYTE const* ilimit;
|
||||
BYTE* oend;
|
||||
BYTE const* iend[4];
|
||||
} HUF_DecompressAsmArgs;
|
||||
} HUF_DecompressFastArgs;
|
||||
|
||||
typedef void (*HUF_DecompressFastLoopFn)(HUF_DecompressFastArgs*);
|
||||
|
||||
/**
|
||||
* Initializes args for the asm decoding loop.
|
||||
* @returns 0 on success
|
||||
* 1 if the fallback implementation should be used.
|
||||
* Initializes args for the fast decoding loop.
|
||||
* @returns 1 on success
|
||||
* 0 if the fallback implementation should be used.
|
||||
* Or an error code on failure.
|
||||
*/
|
||||
static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable)
|
||||
static size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable)
|
||||
{
|
||||
void const* dt = DTable + 1;
|
||||
U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;
|
||||
@@ -173,9 +190,11 @@ static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst,
|
||||
|
||||
BYTE* const oend = (BYTE*)dst + dstSize;
|
||||
|
||||
/* The following condition is false on x32 platform,
|
||||
* but HUF_asm is not compatible with this ABI */
|
||||
if (!(MEM_isLittleEndian() && !MEM_32bits())) return 1;
|
||||
/* The fast decoding loop assumes 64-bit little-endian.
|
||||
* This condition is false on x32.
|
||||
*/
|
||||
if (!MEM_isLittleEndian() || MEM_32bits())
|
||||
return 0;
|
||||
|
||||
/* strict minimum : jump table + 1 byte per stream */
|
||||
if (srcSize < 10)
|
||||
@@ -186,7 +205,7 @@ static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst,
|
||||
* On small inputs we don't have enough data to trigger the fast loop, so use the old decoder.
|
||||
*/
|
||||
if (dtLog != HUF_DECODER_FAST_TABLELOG)
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
/* Read the jump table. */
|
||||
{
|
||||
@@ -200,13 +219,13 @@ static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst,
|
||||
args->iend[2] = args->iend[1] + length2;
|
||||
args->iend[3] = args->iend[2] + length3;
|
||||
|
||||
/* HUF_initDStream() requires this, and this small of an input
|
||||
/* HUF_initFastDStream() requires this, and this small of an input
|
||||
* won't benefit from the ASM loop anyways.
|
||||
* length1 must be >= 16 so that ip[0] >= ilimit before the loop
|
||||
* starts.
|
||||
*/
|
||||
if (length1 < 16 || length2 < 8 || length3 < 8 || length4 < 8)
|
||||
return 1;
|
||||
return 0;
|
||||
if (length4 > srcSize) return ERROR(corruption_detected); /* overflow */
|
||||
}
|
||||
/* ip[] contains the position that is currently loaded into bits[]. */
|
||||
@@ -223,7 +242,7 @@ static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst,
|
||||
|
||||
/* No point to call the ASM loop for tiny outputs. */
|
||||
if (args->op[3] >= oend)
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
/* bits[] is the bit container.
|
||||
* It is read from the MSB down to the LSB.
|
||||
@@ -232,10 +251,10 @@ static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst,
|
||||
* set, so that CountTrailingZeros(bits[]) can be used
|
||||
* to count how many bits we've consumed.
|
||||
*/
|
||||
args->bits[0] = HUF_initDStream(args->ip[0]);
|
||||
args->bits[1] = HUF_initDStream(args->ip[1]);
|
||||
args->bits[2] = HUF_initDStream(args->ip[2]);
|
||||
args->bits[3] = HUF_initDStream(args->ip[3]);
|
||||
args->bits[0] = HUF_initFastDStream(args->ip[0]);
|
||||
args->bits[1] = HUF_initFastDStream(args->ip[1]);
|
||||
args->bits[2] = HUF_initFastDStream(args->ip[2]);
|
||||
args->bits[3] = HUF_initFastDStream(args->ip[3]);
|
||||
|
||||
/* If ip[] >= ilimit, it is guaranteed to be safe to
|
||||
* reload bits[]. It may be beyond its section, but is
|
||||
@@ -246,10 +265,10 @@ static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst,
|
||||
args->oend = oend;
|
||||
args->dt = dt;
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressAsmArgs const* args, int stream, BYTE* segmentEnd)
|
||||
static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressFastArgs const* args, int stream, BYTE* segmentEnd)
|
||||
{
|
||||
/* Validate that we haven't overwritten. */
|
||||
if (args->op[stream] > segmentEnd)
|
||||
@@ -264,7 +283,7 @@ static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressAsmArgs
|
||||
|
||||
/* Construct the BIT_DStream_t. */
|
||||
assert(sizeof(size_t) == 8);
|
||||
bit->bitContainer = MEM_readLE64(args->ip[stream]);
|
||||
bit->bitContainer = MEM_readLEST(args->ip[stream]);
|
||||
bit->bitsConsumed = ZSTD_countTrailingZeros64(args->bits[stream]);
|
||||
bit->start = (const char*)args->iend[0];
|
||||
bit->limitPtr = bit->start + sizeof(size_t);
|
||||
@@ -272,7 +291,6 @@ static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressAsmArgs
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
@@ -289,10 +307,11 @@ typedef struct { BYTE nbBits; BYTE byte; } HUF_DEltX1; /* single-symbol decodi
|
||||
static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {
|
||||
U64 D4;
|
||||
if (MEM_isLittleEndian()) {
|
||||
D4 = (symbol << 8) + nbBits;
|
||||
D4 = (U64)((symbol << 8) + nbBits);
|
||||
} else {
|
||||
D4 = symbol + (nbBits << 8);
|
||||
D4 = (U64)(symbol + (nbBits << 8));
|
||||
}
|
||||
assert(D4 < (1U << 16));
|
||||
D4 *= 0x0001000100010001ULL;
|
||||
return D4;
|
||||
}
|
||||
@@ -335,13 +354,7 @@ typedef struct {
|
||||
BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
|
||||
} HUF_ReadDTableX1_Workspace;
|
||||
|
||||
|
||||
size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
|
||||
{
|
||||
return HUF_readDTableX1_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2)
|
||||
size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
U32 tableLog = 0;
|
||||
U32 nbSymbols = 0;
|
||||
@@ -356,7 +369,7 @@ size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t sr
|
||||
DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
|
||||
/* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), bmi2);
|
||||
iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), flags);
|
||||
if (HUF_isError(iSize)) return iSize;
|
||||
|
||||
|
||||
@@ -383,9 +396,8 @@ size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t sr
|
||||
* rankStart[0] is not filled because there are no entries in the table for
|
||||
* weight 0.
|
||||
*/
|
||||
{
|
||||
int n;
|
||||
int nextRankStart = 0;
|
||||
{ int n;
|
||||
U32 nextRankStart = 0;
|
||||
int const unroll = 4;
|
||||
int const nLimit = (int)nbSymbols - unroll + 1;
|
||||
for (n=0; n<(int)tableLog+1; n++) {
|
||||
@@ -412,10 +424,9 @@ size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t sr
|
||||
* We can switch based on the length to a different inner loop which is
|
||||
* optimized for that particular case.
|
||||
*/
|
||||
{
|
||||
U32 w;
|
||||
int symbol=wksp->rankVal[0];
|
||||
int rankStart=0;
|
||||
{ U32 w;
|
||||
int symbol = wksp->rankVal[0];
|
||||
int rankStart = 0;
|
||||
for (w=1; w<tableLog+1; ++w) {
|
||||
int const symbolCount = wksp->rankVal[w];
|
||||
int const length = (1 << w) >> 1;
|
||||
@@ -525,7 +536,7 @@ HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, cons
|
||||
while (p < pEnd)
|
||||
HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
|
||||
|
||||
return pEnd-pStart;
|
||||
return (size_t)(pEnd-pStart);
|
||||
}
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
@@ -551,6 +562,10 @@ HUF_decompress1X1_usingDTable_internal_body(
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
/* HUF_decompress4X1_usingDTable_internal_body():
|
||||
* Conditions :
|
||||
* @dstSize >= 6
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
HUF_decompress4X1_usingDTable_internal_body(
|
||||
void* dst, size_t dstSize,
|
||||
@@ -594,6 +609,7 @@ HUF_decompress4X1_usingDTable_internal_body(
|
||||
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
|
||||
if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */
|
||||
CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
|
||||
CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
|
||||
CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
|
||||
@@ -656,38 +672,142 @@ size_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, vo
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HUF_NEED_DEFAULT_FUNCTION
|
||||
static
|
||||
size_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
|
||||
size_t cSrcSize, HUF_DTable const* DTable) {
|
||||
return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
|
||||
HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
|
||||
HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;
|
||||
|
||||
static HUF_ASM_X86_64_BMI2_ATTRS
|
||||
#endif
|
||||
|
||||
static HUF_FAST_BMI2_ATTRS
|
||||
void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)
|
||||
{
|
||||
U64 bits[4];
|
||||
BYTE const* ip[4];
|
||||
BYTE* op[4];
|
||||
U16 const* const dtable = (U16 const*)args->dt;
|
||||
BYTE* const oend = args->oend;
|
||||
BYTE const* const ilimit = args->ilimit;
|
||||
|
||||
/* Copy the arguments to local variables */
|
||||
ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
|
||||
ZSTD_memcpy(&ip, &args->ip, sizeof(ip));
|
||||
ZSTD_memcpy(&op, &args->op, sizeof(op));
|
||||
|
||||
assert(MEM_isLittleEndian());
|
||||
assert(!MEM_32bits());
|
||||
|
||||
for (;;) {
|
||||
BYTE* olimit;
|
||||
int stream;
|
||||
int symbol;
|
||||
|
||||
/* Assert loop preconditions */
|
||||
#ifndef NDEBUG
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
assert(op[stream] <= (stream == 3 ? oend : op[stream + 1]));
|
||||
assert(ip[stream] >= ilimit);
|
||||
}
|
||||
#endif
|
||||
/* Compute olimit */
|
||||
{
|
||||
/* Each iteration produces 5 output symbols per stream */
|
||||
size_t const oiters = (size_t)(oend - op[3]) / 5;
|
||||
/* Each iteration consumes up to 11 bits * 5 = 55 bits < 7 bytes
|
||||
* per stream.
|
||||
*/
|
||||
size_t const iiters = (size_t)(ip[0] - ilimit) / 7;
|
||||
/* We can safely run iters iterations before running bounds checks */
|
||||
size_t const iters = MIN(oiters, iiters);
|
||||
size_t const symbols = iters * 5;
|
||||
|
||||
/* We can simply check that op[3] < olimit, instead of checking all
|
||||
* of our bounds, since we can't hit the other bounds until we've run
|
||||
* iters iterations, which only happens when op[3] == olimit.
|
||||
*/
|
||||
olimit = op[3] + symbols;
|
||||
|
||||
/* Exit fast decoding loop once we get close to the end. */
|
||||
if (op[3] + 20 > olimit)
|
||||
break;
|
||||
|
||||
/* Exit the decoding loop if any input pointer has crossed the
|
||||
* previous one. This indicates corruption, and a precondition
|
||||
* to our loop is that ip[i] >= ip[0].
|
||||
*/
|
||||
for (stream = 1; stream < 4; ++stream) {
|
||||
if (ip[stream] < ip[stream - 1])
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (stream = 1; stream < 4; ++stream) {
|
||||
assert(ip[stream] >= ip[stream - 1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
/* Decode 5 symbols in each of the 4 streams */
|
||||
for (symbol = 0; symbol < 5; ++symbol) {
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
int const index = (int)(bits[stream] >> 53);
|
||||
int const entry = (int)dtable[index];
|
||||
bits[stream] <<= (entry & 63);
|
||||
op[stream][symbol] = (BYTE)((entry >> 8) & 0xFF);
|
||||
}
|
||||
}
|
||||
/* Reload the bitstreams */
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
int const ctz = ZSTD_countTrailingZeros64(bits[stream]);
|
||||
int const nbBits = ctz & 7;
|
||||
int const nbBytes = ctz >> 3;
|
||||
op[stream] += 5;
|
||||
ip[stream] -= nbBytes;
|
||||
bits[stream] = MEM_read64(ip[stream]) | 1;
|
||||
bits[stream] <<= nbBits;
|
||||
}
|
||||
} while (op[3] < olimit);
|
||||
}
|
||||
|
||||
_out:
|
||||
|
||||
/* Save the final values of each of the state variables back to args. */
|
||||
ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
|
||||
ZSTD_memcpy(&args->ip, &ip, sizeof(ip));
|
||||
ZSTD_memcpy(&args->op, &op, sizeof(op));
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns @p dstSize on success (>= 6)
|
||||
* 0 if the fallback implementation should be used
|
||||
* An error if an error occurred
|
||||
*/
|
||||
static HUF_FAST_BMI2_ATTRS
|
||||
size_t
|
||||
HUF_decompress4X1_usingDTable_internal_bmi2_asm(
|
||||
HUF_decompress4X1_usingDTable_internal_fast(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable)
|
||||
const HUF_DTable* DTable,
|
||||
HUF_DecompressFastLoopFn loopFn)
|
||||
{
|
||||
void const* dt = DTable + 1;
|
||||
const BYTE* const iend = (const BYTE*)cSrc + 6;
|
||||
BYTE* const oend = (BYTE*)dst + dstSize;
|
||||
HUF_DecompressAsmArgs args;
|
||||
{
|
||||
size_t const ret = HUF_DecompressAsmArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
FORWARD_IF_ERROR(ret, "Failed to init asm args");
|
||||
if (ret != 0)
|
||||
return HUF_decompress4X1_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
HUF_DecompressFastArgs args;
|
||||
{ size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
FORWARD_IF_ERROR(ret, "Failed to init fast loop args");
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(args.ip[0] >= args.ilimit);
|
||||
HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(&args);
|
||||
loopFn(&args);
|
||||
|
||||
/* Our loop guarantees that ip[] >= ilimit and that we haven't
|
||||
* overwritten any op[].
|
||||
@@ -700,8 +820,7 @@ HUF_decompress4X1_usingDTable_internal_bmi2_asm(
|
||||
(void)iend;
|
||||
|
||||
/* finish bit streams one by one. */
|
||||
{
|
||||
size_t const segmentSize = (dstSize+3) / 4;
|
||||
{ size_t const segmentSize = (dstSize+3) / 4;
|
||||
BYTE* segmentEnd = (BYTE*)dst;
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
@@ -718,97 +837,59 @@ HUF_decompress4X1_usingDTable_internal_bmi2_asm(
|
||||
}
|
||||
|
||||
/* decoded size */
|
||||
assert(dstSize != 0);
|
||||
return dstSize;
|
||||
}
|
||||
#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
|
||||
|
||||
typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
|
||||
const void *cSrc,
|
||||
size_t cSrcSize,
|
||||
const HUF_DTable *DTable);
|
||||
|
||||
HUF_DGEN(HUF_decompress1X1_usingDTable_internal)
|
||||
|
||||
static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int bmi2)
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int flags)
|
||||
{
|
||||
HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X1_usingDTable_internal_default;
|
||||
HUF_DecompressFastLoopFn loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop;
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
if (bmi2) {
|
||||
if (flags & HUF_flags_bmi2) {
|
||||
fallbackFn = HUF_decompress4X1_usingDTable_internal_bmi2;
|
||||
# if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
# else
|
||||
return HUF_decompress4X1_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
if (!(flags & HUF_flags_disableAsm)) {
|
||||
loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;
|
||||
}
|
||||
# endif
|
||||
} else {
|
||||
return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
#else
|
||||
(void)bmi2;
|
||||
#endif
|
||||
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
|
||||
return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
#else
|
||||
return HUF_decompress4X1_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
if (!(flags & HUF_flags_disableAsm)) {
|
||||
loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(flags & HUF_flags_disableFast)) {
|
||||
size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
|
||||
size_t HUF_decompress1X1_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = HUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 0) return ERROR(GENERIC);
|
||||
return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
|
||||
static size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
void* workSpace, size_t wkspSize)
|
||||
void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
|
||||
size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);
|
||||
if (HUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
|
||||
return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
|
||||
}
|
||||
|
||||
|
||||
size_t HUF_decompress4X1_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = HUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 0) return ERROR(GENERIC);
|
||||
return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
void* workSpace, size_t wkspSize, int bmi2)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
|
||||
if (HUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
|
||||
}
|
||||
|
||||
size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
void* workSpace, size_t wkspSize)
|
||||
{
|
||||
return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HUF_FORCE_DECOMPRESS_X2 */
|
||||
|
||||
|
||||
@@ -991,7 +1072,7 @@ static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32
|
||||
|
||||
static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
|
||||
const sortedSymbol_t* sortedList,
|
||||
const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
|
||||
const U32* rankStart, rankValCol_t* rankValOrigin, const U32 maxWeight,
|
||||
const U32 nbBitsBaseline)
|
||||
{
|
||||
U32* const rankVal = rankValOrigin[0];
|
||||
@@ -1046,14 +1127,7 @@ typedef struct {
|
||||
|
||||
size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
|
||||
const void* src, size_t srcSize,
|
||||
void* workSpace, size_t wkspSize)
|
||||
{
|
||||
return HUF_readDTableX2_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable,
|
||||
const void* src, size_t srcSize,
|
||||
void* workSpace, size_t wkspSize, int bmi2)
|
||||
void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
U32 tableLog, maxW, nbSymbols;
|
||||
DTableDesc dtd = HUF_getDTableDesc(DTable);
|
||||
@@ -1075,7 +1149,7 @@ size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable,
|
||||
if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
|
||||
/* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
|
||||
|
||||
iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), bmi2);
|
||||
iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), flags);
|
||||
if (HUF_isError(iSize)) return iSize;
|
||||
|
||||
/* check result */
|
||||
@@ -1246,6 +1320,11 @@ HUF_decompress1X2_usingDTable_internal_body(
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
|
||||
/* HUF_decompress4X2_usingDTable_internal_body():
|
||||
* Conditions:
|
||||
* @dstSize >= 6
|
||||
*/
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
HUF_decompress4X2_usingDTable_internal_body(
|
||||
void* dst, size_t dstSize,
|
||||
@@ -1286,8 +1365,9 @@ HUF_decompress4X2_usingDTable_internal_body(
|
||||
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
||||
U32 const dtLog = dtd.tableLog;
|
||||
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
|
||||
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
|
||||
if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
|
||||
if (dstSize < 6) return ERROR(corruption_detected); /* stream 4-split doesn't work */
|
||||
CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
|
||||
CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
|
||||
CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
|
||||
@@ -1372,36 +1452,177 @@ size_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, vo
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HUF_NEED_DEFAULT_FUNCTION
|
||||
static
|
||||
size_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
|
||||
size_t cSrcSize, HUF_DTable const* DTable) {
|
||||
return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
|
||||
HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
|
||||
HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;
|
||||
|
||||
static HUF_ASM_X86_64_BMI2_ATTRS size_t
|
||||
HUF_decompress4X2_usingDTable_internal_bmi2_asm(
|
||||
#endif
|
||||
|
||||
static HUF_FAST_BMI2_ATTRS
|
||||
void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)
|
||||
{
|
||||
U64 bits[4];
|
||||
BYTE const* ip[4];
|
||||
BYTE* op[4];
|
||||
BYTE* oend[4];
|
||||
HUF_DEltX2 const* const dtable = (HUF_DEltX2 const*)args->dt;
|
||||
BYTE const* const ilimit = args->ilimit;
|
||||
|
||||
/* Copy the arguments to local registers. */
|
||||
ZSTD_memcpy(&bits, &args->bits, sizeof(bits));
|
||||
ZSTD_memcpy(&ip, &args->ip, sizeof(ip));
|
||||
ZSTD_memcpy(&op, &args->op, sizeof(op));
|
||||
|
||||
oend[0] = op[1];
|
||||
oend[1] = op[2];
|
||||
oend[2] = op[3];
|
||||
oend[3] = args->oend;
|
||||
|
||||
assert(MEM_isLittleEndian());
|
||||
assert(!MEM_32bits());
|
||||
|
||||
for (;;) {
|
||||
BYTE* olimit;
|
||||
int stream;
|
||||
int symbol;
|
||||
|
||||
/* Assert loop preconditions */
|
||||
#ifndef NDEBUG
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
assert(op[stream] <= oend[stream]);
|
||||
assert(ip[stream] >= ilimit);
|
||||
}
|
||||
#endif
|
||||
/* Compute olimit */
|
||||
{
|
||||
/* Each loop does 5 table lookups for each of the 4 streams.
|
||||
* Each table lookup consumes up to 11 bits of input, and produces
|
||||
* up to 2 bytes of output.
|
||||
*/
|
||||
/* We can consume up to 7 bytes of input per iteration per stream.
|
||||
* We also know that each input pointer is >= ip[0]. So we can run
|
||||
* iters loops before running out of input.
|
||||
*/
|
||||
size_t iters = (size_t)(ip[0] - ilimit) / 7;
|
||||
/* Each iteration can produce up to 10 bytes of output per stream.
|
||||
* Each output stream my advance at different rates. So take the
|
||||
* minimum number of safe iterations among all the output streams.
|
||||
*/
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
size_t const oiters = (size_t)(oend[stream] - op[stream]) / 10;
|
||||
iters = MIN(iters, oiters);
|
||||
}
|
||||
|
||||
/* Each iteration produces at least 5 output symbols. So until
|
||||
* op[3] crosses olimit, we know we haven't executed iters
|
||||
* iterations yet. This saves us maintaining an iters counter,
|
||||
* at the expense of computing the remaining # of iterations
|
||||
* more frequently.
|
||||
*/
|
||||
olimit = op[3] + (iters * 5);
|
||||
|
||||
/* Exit the fast decoding loop if we are too close to the end. */
|
||||
if (op[3] + 10 > olimit)
|
||||
break;
|
||||
|
||||
/* Exit the decoding loop if any input pointer has crossed the
|
||||
* previous one. This indicates corruption, and a precondition
|
||||
* to our loop is that ip[i] >= ip[0].
|
||||
*/
|
||||
for (stream = 1; stream < 4; ++stream) {
|
||||
if (ip[stream] < ip[stream - 1])
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
for (stream = 1; stream < 4; ++stream) {
|
||||
assert(ip[stream] >= ip[stream - 1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
/* Do 5 table lookups for each of the first 3 streams */
|
||||
for (symbol = 0; symbol < 5; ++symbol) {
|
||||
for (stream = 0; stream < 3; ++stream) {
|
||||
int const index = (int)(bits[stream] >> 53);
|
||||
HUF_DEltX2 const entry = dtable[index];
|
||||
MEM_write16(op[stream], entry.sequence);
|
||||
bits[stream] <<= (entry.nbBits);
|
||||
op[stream] += (entry.length);
|
||||
}
|
||||
}
|
||||
/* Do 1 table lookup from the final stream */
|
||||
{
|
||||
int const index = (int)(bits[3] >> 53);
|
||||
HUF_DEltX2 const entry = dtable[index];
|
||||
MEM_write16(op[3], entry.sequence);
|
||||
bits[3] <<= (entry.nbBits);
|
||||
op[3] += (entry.length);
|
||||
}
|
||||
/* Do 4 table lookups from the final stream & reload bitstreams */
|
||||
for (stream = 0; stream < 4; ++stream) {
|
||||
/* Do a table lookup from the final stream.
|
||||
* This is interleaved with the reloading to reduce register
|
||||
* pressure. This shouldn't be necessary, but compilers can
|
||||
* struggle with codegen with high register pressure.
|
||||
*/
|
||||
{
|
||||
int const index = (int)(bits[3] >> 53);
|
||||
HUF_DEltX2 const entry = dtable[index];
|
||||
MEM_write16(op[3], entry.sequence);
|
||||
bits[3] <<= (entry.nbBits);
|
||||
op[3] += (entry.length);
|
||||
}
|
||||
/* Reload the bistreams. The final bitstream must be reloaded
|
||||
* after the 5th symbol was decoded.
|
||||
*/
|
||||
{
|
||||
int const ctz = ZSTD_countTrailingZeros64(bits[stream]);
|
||||
int const nbBits = ctz & 7;
|
||||
int const nbBytes = ctz >> 3;
|
||||
ip[stream] -= nbBytes;
|
||||
bits[stream] = MEM_read64(ip[stream]) | 1;
|
||||
bits[stream] <<= nbBits;
|
||||
}
|
||||
}
|
||||
} while (op[3] < olimit);
|
||||
}
|
||||
|
||||
_out:
|
||||
|
||||
/* Save the final values of each of the state variables back to args. */
|
||||
ZSTD_memcpy(&args->bits, &bits, sizeof(bits));
|
||||
ZSTD_memcpy(&args->ip, &ip, sizeof(ip));
|
||||
ZSTD_memcpy(&args->op, &op, sizeof(op));
|
||||
}
|
||||
|
||||
|
||||
static HUF_FAST_BMI2_ATTRS size_t
|
||||
HUF_decompress4X2_usingDTable_internal_fast(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable) {
|
||||
const HUF_DTable* DTable,
|
||||
HUF_DecompressFastLoopFn loopFn) {
|
||||
void const* dt = DTable + 1;
|
||||
const BYTE* const iend = (const BYTE*)cSrc + 6;
|
||||
BYTE* const oend = (BYTE*)dst + dstSize;
|
||||
HUF_DecompressAsmArgs args;
|
||||
HUF_DecompressFastArgs args;
|
||||
{
|
||||
size_t const ret = HUF_DecompressAsmArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
FORWARD_IF_ERROR(ret, "Failed to init asm args");
|
||||
if (ret != 0)
|
||||
return HUF_decompress4X2_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(args.ip[0] >= args.ilimit);
|
||||
HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(&args);
|
||||
loopFn(&args);
|
||||
|
||||
/* note : op4 already verified within main loop */
|
||||
assert(args.ip[0] >= iend);
|
||||
@@ -1432,91 +1653,72 @@ HUF_decompress4X2_usingDTable_internal_bmi2_asm(
|
||||
/* decoded size */
|
||||
return dstSize;
|
||||
}
|
||||
#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
|
||||
|
||||
static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int bmi2)
|
||||
size_t cSrcSize, HUF_DTable const* DTable, int flags)
|
||||
{
|
||||
HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X2_usingDTable_internal_default;
|
||||
HUF_DecompressFastLoopFn loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop;
|
||||
|
||||
#if DYNAMIC_BMI2
|
||||
if (bmi2) {
|
||||
if (flags & HUF_flags_bmi2) {
|
||||
fallbackFn = HUF_decompress4X2_usingDTable_internal_bmi2;
|
||||
# if ZSTD_ENABLE_ASM_X86_64_BMI2
|
||||
return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
# else
|
||||
return HUF_decompress4X2_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
if (!(flags & HUF_flags_disableAsm)) {
|
||||
loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;
|
||||
}
|
||||
# endif
|
||||
} else {
|
||||
return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
#else
|
||||
(void)bmi2;
|
||||
#endif
|
||||
|
||||
#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
|
||||
return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
#else
|
||||
return HUF_decompress4X2_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
if (!(flags & HUF_flags_disableAsm)) {
|
||||
loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(flags & HUF_flags_disableFast)) {
|
||||
size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);
|
||||
}
|
||||
|
||||
HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
|
||||
|
||||
size_t HUF_decompress1X2_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = HUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 1) return ERROR(GENERIC);
|
||||
return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
void* workSpace, size_t wkspSize)
|
||||
void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,
|
||||
workSpace, wkspSize);
|
||||
workSpace, wkspSize, flags);
|
||||
if (HUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
|
||||
return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, flags);
|
||||
}
|
||||
|
||||
|
||||
size_t HUF_decompress4X2_usingDTable(
|
||||
void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc dtd = HUF_getDTableDesc(DTable);
|
||||
if (dtd.tableType != 1) return ERROR(GENERIC);
|
||||
return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
static size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
void* workSpace, size_t wkspSize, int bmi2)
|
||||
void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,
|
||||
workSpace, wkspSize);
|
||||
workSpace, wkspSize, flags);
|
||||
if (HUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
|
||||
return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
|
||||
}
|
||||
|
||||
size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
void* workSpace, size_t wkspSize)
|
||||
{
|
||||
return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HUF_FORCE_DECOMPRESS_X1 */
|
||||
|
||||
|
||||
@@ -1524,44 +1726,6 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
/* Universal decompression selectors */
|
||||
/* ***********************************/
|
||||
|
||||
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 0);
|
||||
return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 1);
|
||||
return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
#else
|
||||
return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
|
||||
HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
const HUF_DTable* DTable)
|
||||
{
|
||||
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 0);
|
||||
return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 1);
|
||||
return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
#else
|
||||
return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
|
||||
HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
|
||||
@@ -1616,36 +1780,9 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst,
|
||||
size_t dstSize, const void* cSrc,
|
||||
size_t cSrcSize, void* workSpace,
|
||||
size_t wkspSize)
|
||||
{
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
if (cSrcSize == 0) return ERROR(corruption_detected);
|
||||
|
||||
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 0);
|
||||
return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 1);
|
||||
return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
|
||||
#else
|
||||
return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
|
||||
cSrcSize, workSpace, wkspSize):
|
||||
HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize,
|
||||
void* workSpace, size_t wkspSize)
|
||||
void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
@@ -1658,71 +1795,71 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
(void)algoNb;
|
||||
assert(algoNb == 0);
|
||||
return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
|
||||
cSrcSize, workSpace, wkspSize);
|
||||
cSrcSize, workSpace, wkspSize, flags);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 1);
|
||||
return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
|
||||
cSrcSize, workSpace, wkspSize);
|
||||
cSrcSize, workSpace, wkspSize, flags);
|
||||
#else
|
||||
return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
|
||||
cSrcSize, workSpace, wkspSize):
|
||||
cSrcSize, workSpace, wkspSize, flags):
|
||||
HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
|
||||
cSrcSize, workSpace, wkspSize);
|
||||
cSrcSize, workSpace, wkspSize, flags);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
|
||||
size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)
|
||||
{
|
||||
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 0);
|
||||
return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
|
||||
return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 1);
|
||||
return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
|
||||
return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
|
||||
#else
|
||||
return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
|
||||
HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
|
||||
return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :
|
||||
HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
|
||||
size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
const BYTE* ip = (const BYTE*) cSrc;
|
||||
|
||||
size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
|
||||
size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);
|
||||
if (HUF_isError(hSize)) return hSize;
|
||||
if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
|
||||
ip += hSize; cSrcSize -= hSize;
|
||||
|
||||
return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
|
||||
return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
|
||||
size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)
|
||||
{
|
||||
DTableDesc const dtd = HUF_getDTableDesc(DTable);
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 0);
|
||||
return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
|
||||
return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)dtd;
|
||||
assert(dtd.tableType == 1);
|
||||
return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
|
||||
return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
|
||||
#else
|
||||
return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
|
||||
HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
|
||||
return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :
|
||||
HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
|
||||
size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)
|
||||
{
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
@@ -1732,160 +1869,14 @@ size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t ds
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 0);
|
||||
return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
|
||||
return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 1);
|
||||
return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
|
||||
return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
|
||||
#else
|
||||
return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :
|
||||
HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
|
||||
return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags) :
|
||||
HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ZSTD_NO_UNUSED_FUNCTIONS
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_readDTableX1_wksp(DTable, src, srcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
|
||||
return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_readDTableX2_wksp(DTable, src, srcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
|
||||
return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X2
|
||||
size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);
|
||||
return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HUF_FORCE_DECOMPRESS_X1
|
||||
size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);
|
||||
return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
|
||||
|
||||
size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 };
|
||||
#endif
|
||||
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
|
||||
if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
|
||||
if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
|
||||
|
||||
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 0);
|
||||
return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 1);
|
||||
return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);
|
||||
#else
|
||||
return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
/* validation checks */
|
||||
if (dstSize == 0) return ERROR(dstSize_tooSmall);
|
||||
if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
|
||||
if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
|
||||
if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
|
||||
|
||||
{ U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
|
||||
#if defined(HUF_FORCE_DECOMPRESS_X1)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 0);
|
||||
return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
|
||||
#elif defined(HUF_FORCE_DECOMPRESS_X2)
|
||||
(void)algoNb;
|
||||
assert(algoNb == 1);
|
||||
return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);
|
||||
#else
|
||||
return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :
|
||||
HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
|
||||
size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,
|
||||
const void* cSrc, size_t cSrcSize)
|
||||
{
|
||||
U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];
|
||||
return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,
|
||||
workSpace, sizeof(workSpace));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -30,14 +30,14 @@
|
||||
* TODO: Support Windows calling convention.
|
||||
*/
|
||||
|
||||
ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
|
||||
ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
|
||||
ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
|
||||
ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
|
||||
.global HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
|
||||
.global HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
|
||||
.global _HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
|
||||
.global _HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
|
||||
ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_fast_asm_loop)
|
||||
ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_fast_asm_loop)
|
||||
ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_fast_asm_loop)
|
||||
ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_fast_asm_loop)
|
||||
.global HUF_decompress4X1_usingDTable_internal_fast_asm_loop
|
||||
.global HUF_decompress4X2_usingDTable_internal_fast_asm_loop
|
||||
.global _HUF_decompress4X1_usingDTable_internal_fast_asm_loop
|
||||
.global _HUF_decompress4X2_usingDTable_internal_fast_asm_loop
|
||||
.text
|
||||
|
||||
/* Sets up register mappings for clarity.
|
||||
@@ -95,8 +95,9 @@ ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
|
||||
/* Define both _HUF_* & HUF_* symbols because MacOS
|
||||
* C symbols are prefixed with '_' & Linux symbols aren't.
|
||||
*/
|
||||
_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
|
||||
HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
|
||||
_HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
|
||||
HUF_decompress4X1_usingDTable_internal_fast_asm_loop:
|
||||
ZSTD_CET_ENDBRANCH
|
||||
/* Save all registers - even if they are callee saved for simplicity. */
|
||||
push %rax
|
||||
push %rbx
|
||||
@@ -350,8 +351,9 @@ HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
|
||||
pop %rax
|
||||
ret
|
||||
|
||||
_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
|
||||
HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
|
||||
_HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
|
||||
HUF_decompress4X2_usingDTable_internal_fast_asm_loop:
|
||||
ZSTD_CET_ENDBRANCH
|
||||
/* Save all registers - even if they are callee saved for simplicity. */
|
||||
push %rax
|
||||
push %rbx
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "../common/mem.h" /* low level memory routines */
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "../common/fse.h"
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "../common/huf.h"
|
||||
#include "zstd_decompress_internal.h"
|
||||
#include "zstd_ddict.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -59,7 +59,6 @@
|
||||
#include "../common/mem.h" /* low level memory routines */
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "../common/fse.h"
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "../common/huf.h"
|
||||
#include "../common/xxhash.h" /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */
|
||||
#include "../common/zstd_internal.h" /* blockProperties_t */
|
||||
@@ -244,6 +243,7 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
|
||||
dctx->outBufferMode = ZSTD_bm_buffered;
|
||||
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
|
||||
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
|
||||
dctx->disableHufAsm = 0;
|
||||
}
|
||||
|
||||
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
||||
@@ -782,10 +782,11 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize
|
||||
ip += 4;
|
||||
}
|
||||
|
||||
frameSizeInfo.nbBlocks = nbBlocks;
|
||||
frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
|
||||
frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
? zfh.frameContentSize
|
||||
: nbBlocks * zfh.blockSizeMax;
|
||||
: (unsigned long long)nbBlocks * zfh.blockSizeMax;
|
||||
return frameSizeInfo;
|
||||
}
|
||||
}
|
||||
@@ -825,6 +826,48 @@ unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
|
||||
return bound;
|
||||
}
|
||||
|
||||
size_t ZSTD_decompressionMargin(void const* src, size_t srcSize)
|
||||
{
|
||||
size_t margin = 0;
|
||||
unsigned maxBlockSize = 0;
|
||||
|
||||
/* Iterate over each frame */
|
||||
while (srcSize > 0) {
|
||||
ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
|
||||
size_t const compressedSize = frameSizeInfo.compressedSize;
|
||||
unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
|
||||
ZSTD_frameHeader zfh;
|
||||
|
||||
FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), "");
|
||||
if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
|
||||
return ERROR(corruption_detected);
|
||||
|
||||
if (zfh.frameType == ZSTD_frame) {
|
||||
/* Add the frame header to our margin */
|
||||
margin += zfh.headerSize;
|
||||
/* Add the checksum to our margin */
|
||||
margin += zfh.checksumFlag ? 4 : 0;
|
||||
/* Add 3 bytes per block */
|
||||
margin += 3 * frameSizeInfo.nbBlocks;
|
||||
|
||||
/* Compute the max block size */
|
||||
maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);
|
||||
} else {
|
||||
assert(zfh.frameType == ZSTD_skippableFrame);
|
||||
/* Add the entire skippable frame size to our margin. */
|
||||
margin += compressedSize;
|
||||
}
|
||||
|
||||
assert(srcSize >= compressedSize);
|
||||
src = (const BYTE*)src + compressedSize;
|
||||
srcSize -= compressedSize;
|
||||
}
|
||||
|
||||
/* Add the max block size back to the margin. */
|
||||
margin += maxBlockSize;
|
||||
|
||||
return margin;
|
||||
}
|
||||
|
||||
/*-*************************************************************
|
||||
* Frame decoding
|
||||
@@ -850,7 +893,7 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
|
||||
if (srcSize == 0) return 0;
|
||||
RETURN_ERROR(dstBuffer_null, "");
|
||||
}
|
||||
ZSTD_memcpy(dst, src, srcSize);
|
||||
ZSTD_memmove(dst, src, srcSize);
|
||||
return srcSize;
|
||||
}
|
||||
|
||||
@@ -928,6 +971,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
|
||||
/* Loop on each block */
|
||||
while (1) {
|
||||
BYTE* oBlockEnd = oend;
|
||||
size_t decodedSize;
|
||||
blockProperties_t blockProperties;
|
||||
size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
|
||||
@@ -937,16 +981,34 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
remainingSrcSize -= ZSTD_blockHeaderSize;
|
||||
RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
|
||||
|
||||
if (ip >= op && ip < oBlockEnd) {
|
||||
/* We are decompressing in-place. Limit the output pointer so that we
|
||||
* don't overwrite the block that we are currently reading. This will
|
||||
* fail decompression if the input & output pointers aren't spaced
|
||||
* far enough apart.
|
||||
*
|
||||
* This is important to set, even when the pointers are far enough
|
||||
* apart, because ZSTD_decompressBlock_internal() can decide to store
|
||||
* literals in the output buffer, after the block it is decompressing.
|
||||
* Since we don't want anything to overwrite our input, we have to tell
|
||||
* ZSTD_decompressBlock_internal to never write past ip.
|
||||
*
|
||||
* See ZSTD_allocateLiteralsBuffer() for reference.
|
||||
*/
|
||||
oBlockEnd = op + (ip - op);
|
||||
}
|
||||
|
||||
switch(blockProperties.blockType)
|
||||
{
|
||||
case bt_compressed:
|
||||
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
|
||||
decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, /* frame */ 1, not_streaming);
|
||||
break;
|
||||
case bt_raw :
|
||||
/* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */
|
||||
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
|
||||
break;
|
||||
case bt_rle :
|
||||
decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
|
||||
decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);
|
||||
break;
|
||||
case bt_reserved :
|
||||
default:
|
||||
@@ -981,6 +1043,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
|
||||
}
|
||||
ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
|
||||
/* Allow caller to get size read */
|
||||
DEBUGLOG(4, "ZSTD_decompressFrame: decompressed frame of size %zi, consuming %zi bytes of input", op-ostart, ip - (const BYTE*)*srcPtr);
|
||||
*srcPtr = ip;
|
||||
*srcSizePtr = remainingSrcSize;
|
||||
return (size_t)(op-ostart);
|
||||
@@ -1375,11 +1438,11 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
|
||||
/* in minimal huffman, we always use X1 variants */
|
||||
size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
|
||||
dictPtr, dictEnd - dictPtr,
|
||||
workspace, workspaceSize);
|
||||
workspace, workspaceSize, /* flags */ 0);
|
||||
#else
|
||||
size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
|
||||
dictPtr, (size_t)(dictEnd - dictPtr),
|
||||
workspace, workspaceSize);
|
||||
workspace, workspaceSize, /* flags */ 0);
|
||||
#endif
|
||||
RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
|
||||
dictPtr += hSize;
|
||||
@@ -1549,7 +1612,7 @@ unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
|
||||
* ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
||||
unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
|
||||
ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };
|
||||
size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
|
||||
if (ZSTD_isError(hError)) return 0;
|
||||
return zfp.dictID;
|
||||
@@ -1656,7 +1719,9 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
|
||||
size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initDStream");
|
||||
return ZSTD_initDStream_usingDDict(zds, NULL);
|
||||
FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), "");
|
||||
FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), "");
|
||||
return ZSTD_startingInputLength(zds->format);
|
||||
}
|
||||
|
||||
/* ZSTD_initDStream_usingDDict() :
|
||||
@@ -1664,6 +1729,7 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
|
||||
* this function cannot fail */
|
||||
size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_initDStream_usingDDict");
|
||||
FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
|
||||
FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
|
||||
return ZSTD_startingInputLength(dctx->format);
|
||||
@@ -1674,6 +1740,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
|
||||
* this function cannot fail */
|
||||
size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
|
||||
{
|
||||
DEBUGLOG(4, "ZSTD_resetDStream");
|
||||
FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
|
||||
return ZSTD_startingInputLength(dctx->format);
|
||||
}
|
||||
@@ -1745,6 +1812,11 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
||||
bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
|
||||
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
|
||||
return bounds;
|
||||
case ZSTD_d_disableHuffmanAssembly:
|
||||
bounds.lowerBound = 0;
|
||||
bounds.upperBound = 1;
|
||||
return bounds;
|
||||
|
||||
default:;
|
||||
}
|
||||
bounds.error = ERROR(parameter_unsupported);
|
||||
@@ -1785,6 +1857,9 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
|
||||
case ZSTD_d_refMultipleDDicts:
|
||||
*value = (int)dctx->refMultipleDDicts;
|
||||
return 0;
|
||||
case ZSTD_d_disableHuffmanAssembly:
|
||||
*value = (int)dctx->disableHufAsm;
|
||||
return 0;
|
||||
default:;
|
||||
}
|
||||
RETURN_ERROR(parameter_unsupported, "");
|
||||
@@ -1818,6 +1893,10 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
||||
}
|
||||
dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
|
||||
return 0;
|
||||
case ZSTD_d_disableHuffmanAssembly:
|
||||
CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
|
||||
dctx->disableHufAsm = value != 0;
|
||||
return 0;
|
||||
default:;
|
||||
}
|
||||
RETURN_ERROR(parameter_unsupported, "");
|
||||
@@ -2058,6 +2137,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
|
||||
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
||||
DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
|
||||
assert(istart != NULL);
|
||||
ip = istart + cSize;
|
||||
op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */
|
||||
zds->expected = 0;
|
||||
@@ -2143,6 +2223,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
}
|
||||
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
||||
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
|
||||
assert(ip != NULL);
|
||||
ip += neededInSize;
|
||||
/* Function modifies the stage so we must break */
|
||||
break;
|
||||
@@ -2157,7 +2238,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
||||
size_t loadedSize;
|
||||
/* At this point we shouldn't be decompressing a block that we can stream. */
|
||||
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
|
||||
assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));
|
||||
if (isSkipFrame) {
|
||||
loadedSize = MIN(toLoad, (size_t)(iend-ip));
|
||||
} else {
|
||||
@@ -2166,8 +2247,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
"should never happen");
|
||||
loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
|
||||
}
|
||||
ip += loadedSize;
|
||||
zds->inPos += loadedSize;
|
||||
if (loadedSize != 0) {
|
||||
/* ip may be NULL */
|
||||
ip += loadedSize;
|
||||
zds->inPos += loadedSize;
|
||||
}
|
||||
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
||||
|
||||
/* decode loaded input */
|
||||
@@ -2214,8 +2298,8 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
||||
zds->noForwardProgress ++;
|
||||
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
||||
RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
|
||||
RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
|
||||
RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, "");
|
||||
RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, "");
|
||||
assert(0);
|
||||
}
|
||||
} else {
|
||||
@@ -2252,11 +2336,17 @@ size_t ZSTD_decompressStream_simpleArgs (
|
||||
void* dst, size_t dstCapacity, size_t* dstPos,
|
||||
const void* src, size_t srcSize, size_t* srcPos)
|
||||
{
|
||||
ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
|
||||
ZSTD_inBuffer input = { src, srcSize, *srcPos };
|
||||
/* ZSTD_compress_generic() will check validity of dstPos and srcPos */
|
||||
size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
|
||||
*dstPos = output.pos;
|
||||
*srcPos = input.pos;
|
||||
return cErr;
|
||||
ZSTD_outBuffer output;
|
||||
ZSTD_inBuffer input;
|
||||
output.dst = dst;
|
||||
output.size = dstCapacity;
|
||||
output.pos = *dstPos;
|
||||
input.src = src;
|
||||
input.size = srcSize;
|
||||
input.pos = *srcPos;
|
||||
{ size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
|
||||
*dstPos = output.pos;
|
||||
*srcPos = input.pos;
|
||||
return cErr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "../common/mem.h" /* low level memory routines */
|
||||
#define FSE_STATIC_LINKING_ONLY
|
||||
#include "../common/fse.h"
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "../common/huf.h"
|
||||
#include "../common/zstd_internal.h"
|
||||
#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
|
||||
@@ -142,6 +141,9 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
U32 const lhc = MEM_readLE32(istart);
|
||||
size_t hufSuccess;
|
||||
size_t expectedWriteSize = MIN(ZSTD_BLOCKSIZE_MAX, dstCapacity);
|
||||
int const flags = 0
|
||||
| (ZSTD_DCtx_get_bmi2(dctx) ? HUF_flags_bmi2 : 0)
|
||||
| (dctx->disableHufAsm ? HUF_flags_disableAsm : 0);
|
||||
switch(lhlCode)
|
||||
{
|
||||
case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
|
||||
@@ -166,6 +168,10 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
}
|
||||
RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled");
|
||||
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
|
||||
if (!singleStream)
|
||||
RETURN_ERROR_IF(litSize < MIN_LITERALS_FOR_4_STREAMS, literals_headerWrong,
|
||||
"Not enough literals (%zu) for the 4-streams mode (min %u)",
|
||||
litSize, MIN_LITERALS_FOR_4_STREAMS);
|
||||
RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, "");
|
||||
RETURN_ERROR_IF(expectedWriteSize < litSize , dstSize_tooSmall, "");
|
||||
ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 0);
|
||||
@@ -177,13 +183,14 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
|
||||
if (litEncType==set_repeat) {
|
||||
if (singleStream) {
|
||||
hufSuccess = HUF_decompress1X_usingDTable_bmi2(
|
||||
hufSuccess = HUF_decompress1X_usingDTable(
|
||||
dctx->litBuffer, litSize, istart+lhSize, litCSize,
|
||||
dctx->HUFptr, ZSTD_DCtx_get_bmi2(dctx));
|
||||
dctx->HUFptr, flags);
|
||||
} else {
|
||||
hufSuccess = HUF_decompress4X_usingDTable_bmi2(
|
||||
assert(litSize >= MIN_LITERALS_FOR_4_STREAMS);
|
||||
hufSuccess = HUF_decompress4X_usingDTable(
|
||||
dctx->litBuffer, litSize, istart+lhSize, litCSize,
|
||||
dctx->HUFptr, ZSTD_DCtx_get_bmi2(dctx));
|
||||
dctx->HUFptr, flags);
|
||||
}
|
||||
} else {
|
||||
if (singleStream) {
|
||||
@@ -191,18 +198,18 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
hufSuccess = HUF_decompress1X_DCtx_wksp(
|
||||
dctx->entropy.hufTable, dctx->litBuffer, litSize,
|
||||
istart+lhSize, litCSize, dctx->workspace,
|
||||
sizeof(dctx->workspace));
|
||||
sizeof(dctx->workspace), flags);
|
||||
#else
|
||||
hufSuccess = HUF_decompress1X1_DCtx_wksp_bmi2(
|
||||
hufSuccess = HUF_decompress1X1_DCtx_wksp(
|
||||
dctx->entropy.hufTable, dctx->litBuffer, litSize,
|
||||
istart+lhSize, litCSize, dctx->workspace,
|
||||
sizeof(dctx->workspace), ZSTD_DCtx_get_bmi2(dctx));
|
||||
sizeof(dctx->workspace), flags);
|
||||
#endif
|
||||
} else {
|
||||
hufSuccess = HUF_decompress4X_hufOnly_wksp_bmi2(
|
||||
hufSuccess = HUF_decompress4X_hufOnly_wksp(
|
||||
dctx->entropy.hufTable, dctx->litBuffer, litSize,
|
||||
istart+lhSize, litCSize, dctx->workspace,
|
||||
sizeof(dctx->workspace), ZSTD_DCtx_get_bmi2(dctx));
|
||||
sizeof(dctx->workspace), flags);
|
||||
}
|
||||
}
|
||||
if (dctx->litBufferLocation == ZSTD_split)
|
||||
@@ -509,7 +516,8 @@ void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,
|
||||
for (i = 8; i < n; i += 8) {
|
||||
MEM_write64(spread + pos + i, sv);
|
||||
}
|
||||
pos += n;
|
||||
assert(n>=0);
|
||||
pos += (size_t)n;
|
||||
}
|
||||
}
|
||||
/* Now we spread those positions across the table.
|
||||
@@ -1162,7 +1170,7 @@ ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, U16
|
||||
}
|
||||
|
||||
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
|
||||
* offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
|
||||
* offset bits. But we can only read at most STREAM_ACCUMULATOR_MIN_32
|
||||
* bits before reloading. This value is the maximum number of bytes we read
|
||||
* after reloading when we are decoding long offsets.
|
||||
*/
|
||||
@@ -1212,6 +1220,10 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
|
||||
U32 const llnbBits = llDInfo->nbBits;
|
||||
U32 const mlnbBits = mlDInfo->nbBits;
|
||||
U32 const ofnbBits = ofDInfo->nbBits;
|
||||
|
||||
assert(llBits <= MaxLLBits);
|
||||
assert(mlBits <= MaxMLBits);
|
||||
assert(ofBits <= MaxOff);
|
||||
/*
|
||||
* As gcc has better branch and block analyzers, sometimes it is only
|
||||
* valuable to mark likeliness for clang, it gives around 3-4% of
|
||||
@@ -1227,13 +1239,16 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
|
||||
#endif
|
||||
ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
|
||||
ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
|
||||
assert(ofBits <= MaxOff);
|
||||
ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 > LONG_OFFSETS_MAX_EXTRA_BITS_32);
|
||||
ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32 >= MaxMLBits);
|
||||
if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
|
||||
U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
|
||||
/* Always read extra bits, this keeps the logic simple,
|
||||
* avoids branches, and avoids accidentally reading 0 bits.
|
||||
*/
|
||||
U32 const extraBits = LONG_OFFSETS_MAX_EXTRA_BITS_32;
|
||||
offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
|
||||
BIT_reloadDStream(&seqState->DStream);
|
||||
if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
|
||||
assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */
|
||||
offset += BIT_readBitsFast(&seqState->DStream, extraBits);
|
||||
} else {
|
||||
offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
|
||||
if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
|
||||
@@ -1971,34 +1986,79 @@ ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
|
||||
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
|
||||
|
||||
|
||||
/**
|
||||
* @returns The total size of the history referencable by zstd, including
|
||||
* both the prefix and the extDict. At @p op any offset larger than this
|
||||
* is invalid.
|
||||
*/
|
||||
static size_t ZSTD_totalHistorySize(BYTE* op, BYTE const* virtualStart)
|
||||
{
|
||||
return (size_t)(op - virtualStart);
|
||||
}
|
||||
|
||||
#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
|
||||
!defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
|
||||
/* ZSTD_getLongOffsetsShare() :
|
||||
typedef struct {
|
||||
unsigned longOffsetShare;
|
||||
unsigned maxNbAdditionalBits;
|
||||
} ZSTD_OffsetInfo;
|
||||
|
||||
/* ZSTD_getOffsetInfo() :
|
||||
* condition : offTable must be valid
|
||||
* @return : "share" of long offsets (arbitrarily defined as > (1<<23))
|
||||
* compared to maximum possible of (1<<OffFSELog) */
|
||||
static unsigned
|
||||
ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable)
|
||||
* compared to maximum possible of (1<<OffFSELog),
|
||||
* as well as the maximum number additional bits required.
|
||||
*/
|
||||
static ZSTD_OffsetInfo
|
||||
ZSTD_getOffsetInfo(const ZSTD_seqSymbol* offTable, int nbSeq)
|
||||
{
|
||||
const void* ptr = offTable;
|
||||
U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;
|
||||
const ZSTD_seqSymbol* table = offTable + 1;
|
||||
U32 const max = 1 << tableLog;
|
||||
U32 u, total = 0;
|
||||
DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog);
|
||||
ZSTD_OffsetInfo info = {0, 0};
|
||||
/* If nbSeq == 0, then the offTable is uninitialized, but we have
|
||||
* no sequences, so both values should be 0.
|
||||
*/
|
||||
if (nbSeq != 0) {
|
||||
const void* ptr = offTable;
|
||||
U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;
|
||||
const ZSTD_seqSymbol* table = offTable + 1;
|
||||
U32 const max = 1 << tableLog;
|
||||
U32 u;
|
||||
DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog);
|
||||
|
||||
assert(max <= (1 << OffFSELog)); /* max not too large */
|
||||
for (u=0; u<max; u++) {
|
||||
if (table[u].nbAdditionalBits > 22) total += 1;
|
||||
assert(max <= (1 << OffFSELog)); /* max not too large */
|
||||
for (u=0; u<max; u++) {
|
||||
info.maxNbAdditionalBits = MAX(info.maxNbAdditionalBits, table[u].nbAdditionalBits);
|
||||
if (table[u].nbAdditionalBits > 22) info.longOffsetShare += 1;
|
||||
}
|
||||
|
||||
assert(tableLog <= OffFSELog);
|
||||
info.longOffsetShare <<= (OffFSELog - tableLog); /* scale to OffFSELog */
|
||||
}
|
||||
|
||||
assert(tableLog <= OffFSELog);
|
||||
total <<= (OffFSELog - tableLog); /* scale to OffFSELog */
|
||||
return info;
|
||||
}
|
||||
|
||||
return total;
|
||||
/**
|
||||
* @returns The maximum offset we can decode in one read of our bitstream, without
|
||||
* reloading more bits in the middle of the offset bits read. Any offsets larger
|
||||
* than this must use the long offset decoder.
|
||||
*/
|
||||
static size_t ZSTD_maxShortOffset(void)
|
||||
{
|
||||
if (MEM_64bits()) {
|
||||
/* We can decode any offset without reloading bits.
|
||||
* This might change if the max window size grows.
|
||||
*/
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);
|
||||
return (size_t)-1;
|
||||
} else {
|
||||
/* The maximum offBase is (1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1.
|
||||
* This offBase would require STREAM_ACCUMULATOR_MIN extra bits.
|
||||
* Then we have to subtract ZSTD_REP_NUM to get the maximum possible offset.
|
||||
*/
|
||||
size_t const maxOffbase = ((size_t)1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1;
|
||||
size_t const maxOffset = maxOffbase - ZSTD_REP_NUM;
|
||||
assert(ZSTD_highbit32((U32)maxOffbase) == STREAM_ACCUMULATOR_MIN);
|
||||
return maxOffset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t
|
||||
ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
@@ -2006,16 +2066,17 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
const void* src, size_t srcSize, const int frame, const streaming_operation streaming)
|
||||
{ /* blockType == blockCompressed */
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
/* isLongOffset must be true if there are long offsets.
|
||||
* Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
|
||||
* We don't expect that to be the case in 64-bit mode.
|
||||
* In block mode, window size is not known, so we have to be conservative.
|
||||
* (note: but it could be evaluated from current-lowLimit)
|
||||
*/
|
||||
ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
|
||||
DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
|
||||
|
||||
RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong, "");
|
||||
/* Note : the wording of the specification
|
||||
* allows compressed block to be sized exactly ZSTD_BLOCKSIZE_MAX.
|
||||
* This generally does not happen, as it makes little sense,
|
||||
* since an uncompressed block would feature same size and have no decompression cost.
|
||||
* Also, note that decoder from reference libzstd before < v1.5.4
|
||||
* would consider this edge case as an error.
|
||||
* As a consequence, avoid generating compressed blocks of size ZSTD_BLOCKSIZE_MAX
|
||||
* for broader compatibility with the deployed ecosystem of zstd decoders */
|
||||
RETURN_ERROR_IF(srcSize > ZSTD_BLOCKSIZE_MAX, srcSize_wrong, "");
|
||||
|
||||
/* Decode literals section */
|
||||
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, streaming);
|
||||
@@ -2027,6 +2088,23 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
|
||||
/* Build Decoding Tables */
|
||||
{
|
||||
/* Compute the maximum block size, which must also work when !frame and fParams are unset.
|
||||
* Additionally, take the min with dstCapacity to ensure that the totalHistorySize fits in a size_t.
|
||||
*/
|
||||
size_t const blockSizeMax = MIN(dstCapacity, (frame ? dctx->fParams.blockSizeMax : ZSTD_BLOCKSIZE_MAX));
|
||||
size_t const totalHistorySize = ZSTD_totalHistorySize((BYTE*)dst + blockSizeMax, (BYTE const*)dctx->virtualStart);
|
||||
/* isLongOffset must be true if there are long offsets.
|
||||
* Offsets are long if they are larger than ZSTD_maxShortOffset().
|
||||
* We don't expect that to be the case in 64-bit mode.
|
||||
*
|
||||
* We check here to see if our history is large enough to allow long offsets.
|
||||
* If it isn't, then we can't possible have (valid) long offsets. If the offset
|
||||
* is invalid, then it is okay to read it incorrectly.
|
||||
*
|
||||
* If isLongOffsets is true, then we will later check our decoding table to see
|
||||
* if it is even possible to generate long offsets.
|
||||
*/
|
||||
ZSTD_longOffset_e isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (totalHistorySize > ZSTD_maxShortOffset()));
|
||||
/* These macros control at build-time which decompressor implementation
|
||||
* we use. If neither is defined, we do some inspection and dispatch at
|
||||
* runtime.
|
||||
@@ -2034,6 +2112,11 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
|
||||
!defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
|
||||
int usePrefetchDecoder = dctx->ddictIsCold;
|
||||
#else
|
||||
/* Set to 1 to avoid computing offset info if we don't need to.
|
||||
* Otherwise this value is ignored.
|
||||
*/
|
||||
int usePrefetchDecoder = 1;
|
||||
#endif
|
||||
int nbSeq;
|
||||
size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);
|
||||
@@ -2043,26 +2126,38 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
|
||||
RETURN_ERROR_IF(dst == NULL && nbSeq > 0, dstSize_tooSmall, "NULL not handled");
|
||||
|
||||
#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
|
||||
!defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
|
||||
if ( !usePrefetchDecoder
|
||||
&& (!frame || (dctx->fParams.windowSize > (1<<24)))
|
||||
&& (nbSeq>ADVANCED_SEQS) ) { /* could probably use a larger nbSeq limit */
|
||||
U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr);
|
||||
U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */
|
||||
usePrefetchDecoder = (shareLongOffsets >= minShare);
|
||||
/* If we could potentially have long offsets, or we might want to use the prefetch decoder,
|
||||
* compute information about the share of long offsets, and the maximum nbAdditionalBits.
|
||||
* NOTE: could probably use a larger nbSeq limit
|
||||
*/
|
||||
if (isLongOffset || (!usePrefetchDecoder && (totalHistorySize > (1u << 24)) && (nbSeq > 8))) {
|
||||
ZSTD_OffsetInfo const info = ZSTD_getOffsetInfo(dctx->OFTptr, nbSeq);
|
||||
if (isLongOffset && info.maxNbAdditionalBits <= STREAM_ACCUMULATOR_MIN) {
|
||||
/* If isLongOffset, but the maximum number of additional bits that we see in our table is small
|
||||
* enough, then we know it is impossible to have too long an offset in this block, so we can
|
||||
* use the regular offset decoder.
|
||||
*/
|
||||
isLongOffset = ZSTD_lo_isRegularOffset;
|
||||
}
|
||||
if (!usePrefetchDecoder) {
|
||||
U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */
|
||||
usePrefetchDecoder = (info.longOffsetShare >= minShare);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dctx->ddictIsCold = 0;
|
||||
|
||||
#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
|
||||
!defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
|
||||
if (usePrefetchDecoder)
|
||||
if (usePrefetchDecoder) {
|
||||
#else
|
||||
(void)usePrefetchDecoder;
|
||||
{
|
||||
#endif
|
||||
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
|
||||
return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
|
||||
/* else */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -165,6 +165,7 @@ struct ZSTD_DCtx_s
|
||||
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) */
|
||||
int disableHufAsm;
|
||||
|
||||
/* streaming */
|
||||
ZSTD_dStreamStage streamStage;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -13,6 +13,8 @@
|
||||
/* *************************************
|
||||
* Dependencies
|
||||
***************************************/
|
||||
#define ZSTD_DISABLE_DEPRECATE_WARNINGS /* suppress warning on ZSTD_initDStream_usingDict */
|
||||
#include "../zstd.h" /* ZSTD_CStream, ZSTD_DStream, ZSTDLIB_API */
|
||||
#define ZBUFF_STATIC_LINKING_ONLY
|
||||
#include "zbuff.h"
|
||||
|
||||
|
||||
+17
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -647,7 +647,7 @@ static size_t COVER_ctx_init(COVER_ctx_t *ctx, const void *samplesBuffer,
|
||||
|
||||
void COVER_warnOnSmallCorpus(size_t maxDictSize, size_t nbDmers, int displayLevel)
|
||||
{
|
||||
const double ratio = (double)nbDmers / maxDictSize;
|
||||
const double ratio = (double)nbDmers / (double)maxDictSize;
|
||||
if (ratio >= 10) {
|
||||
return;
|
||||
}
|
||||
@@ -951,9 +951,17 @@ void COVER_best_finish(COVER_best_t *best, ZDICT_cover_params_t parameters,
|
||||
}
|
||||
}
|
||||
|
||||
static COVER_dictSelection_t setDictSelection(BYTE* buf, size_t s, size_t csz)
|
||||
{
|
||||
COVER_dictSelection_t ds;
|
||||
ds.dictContent = buf;
|
||||
ds.dictSize = s;
|
||||
ds.totalCompressedSize = csz;
|
||||
return ds;
|
||||
}
|
||||
|
||||
COVER_dictSelection_t COVER_dictSelectionError(size_t error) {
|
||||
COVER_dictSelection_t selection = { NULL, 0, error };
|
||||
return selection;
|
||||
return setDictSelection(NULL, 0, error);
|
||||
}
|
||||
|
||||
unsigned COVER_dictSelectionIsError(COVER_dictSelection_t selection) {
|
||||
@@ -1006,9 +1014,8 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBuffe
|
||||
}
|
||||
|
||||
if (params.shrinkDict == 0) {
|
||||
COVER_dictSelection_t selection = { largestDictbuffer, dictContentSize, totalCompressedSize };
|
||||
free(candidateDictBuffer);
|
||||
return selection;
|
||||
return setDictSelection(largestDictbuffer, dictContentSize, totalCompressedSize);
|
||||
}
|
||||
|
||||
largestDict = dictContentSize;
|
||||
@@ -1040,20 +1047,16 @@ COVER_dictSelection_t COVER_selectDict(BYTE* customDictContent, size_t dictBuffe
|
||||
return COVER_dictSelectionError(totalCompressedSize);
|
||||
}
|
||||
|
||||
if (totalCompressedSize <= largestCompressed * regressionTolerance) {
|
||||
COVER_dictSelection_t selection = { candidateDictBuffer, dictContentSize, totalCompressedSize };
|
||||
if ((double)totalCompressedSize <= (double)largestCompressed * regressionTolerance) {
|
||||
free(largestDictbuffer);
|
||||
return selection;
|
||||
return setDictSelection( candidateDictBuffer, dictContentSize, totalCompressedSize );
|
||||
}
|
||||
dictContentSize *= 2;
|
||||
}
|
||||
dictContentSize = largestDict;
|
||||
totalCompressedSize = largestCompressed;
|
||||
{
|
||||
COVER_dictSelection_t selection = { largestDictbuffer, dictContentSize, totalCompressedSize };
|
||||
free(candidateDictBuffer);
|
||||
return selection;
|
||||
}
|
||||
free(candidateDictBuffer);
|
||||
return setDictSelection( largestDictbuffer, dictContentSize, totalCompressedSize );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -44,7 +44,6 @@
|
||||
#ifndef ZDICT_STATIC_LINKING_ONLY
|
||||
# define ZDICT_STATIC_LINKING_ONLY
|
||||
#endif
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
|
||||
#include "../common/mem.h" /* read */
|
||||
#include "../common/fse.h" /* FSE_normalizeCount, FSE_writeNCount */
|
||||
@@ -373,7 +372,7 @@ static U32 ZDICT_tryMerge(dictItem* table, dictItem elt, U32 eltNbToSkip, const
|
||||
elt = table[u];
|
||||
/* sort : improve rank */
|
||||
while ((u>1) && (table[u-1].savings < elt.savings))
|
||||
table[u] = table[u-1], u--;
|
||||
table[u] = table[u-1], u--;
|
||||
table[u] = elt;
|
||||
return u;
|
||||
} }
|
||||
@@ -524,7 +523,7 @@ static size_t ZDICT_trainBuffer_legacy(dictItem* dictList, U32 dictListSize,
|
||||
if (solution.length==0) { cursor++; continue; }
|
||||
ZDICT_insertDictItem(dictList, dictListSize, solution, buffer);
|
||||
cursor += solution.length;
|
||||
DISPLAYUPDATE(2, "\r%4.2f %% \r", (double)cursor / bufferSize * 100);
|
||||
DISPLAYUPDATE(2, "\r%4.2f %% \r", (double)cursor / (double)bufferSize * 100.0);
|
||||
} }
|
||||
|
||||
_cleanup:
|
||||
@@ -676,6 +675,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
size_t const totalSrcSize = ZDICT_totalSampleSize(fileSizes, nbFiles);
|
||||
size_t const averageSampleSize = totalSrcSize / (nbFiles + !nbFiles);
|
||||
BYTE* dstPtr = (BYTE*)dstBuffer;
|
||||
U32 wksp[HUF_CTABLE_WORKSPACE_SIZE_U32];
|
||||
|
||||
/* init */
|
||||
DEBUGLOG(4, "ZDICT_analyzeEntropy");
|
||||
@@ -716,7 +716,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
} }
|
||||
|
||||
/* analyze, build stats, starting with literals */
|
||||
{ size_t maxNbBits = HUF_buildCTable (hufTable, countLit, 255, huffLog);
|
||||
{ size_t maxNbBits = HUF_buildCTable_wksp(hufTable, countLit, 255, huffLog, wksp, sizeof(wksp));
|
||||
if (HUF_isError(maxNbBits)) {
|
||||
eSize = maxNbBits;
|
||||
DISPLAYLEVEL(1, " HUF_buildCTable error \n");
|
||||
@@ -725,7 +725,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
if (maxNbBits==8) { /* not compressible : will fail on HUF_writeCTable() */
|
||||
DISPLAYLEVEL(2, "warning : pathological dataset : literals are not compressible : samples are noisy or too regular \n");
|
||||
ZDICT_flatLit(countLit); /* replace distribution by a fake "mostly flat but still compressible" distribution, that HUF_writeCTable() can encode */
|
||||
maxNbBits = HUF_buildCTable (hufTable, countLit, 255, huffLog);
|
||||
maxNbBits = HUF_buildCTable_wksp(hufTable, countLit, 255, huffLog, wksp, sizeof(wksp));
|
||||
assert(maxNbBits==9);
|
||||
}
|
||||
huffLog = (U32)maxNbBits;
|
||||
@@ -766,7 +766,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
llLog = (U32)errorCode;
|
||||
|
||||
/* write result to buffer */
|
||||
{ size_t const hhSize = HUF_writeCTable(dstPtr, maxDstSize, hufTable, 255, huffLog);
|
||||
{ size_t const hhSize = HUF_writeCTable_wksp(dstPtr, maxDstSize, hufTable, 255, huffLog, wksp, sizeof(wksp));
|
||||
if (HUF_isError(hhSize)) {
|
||||
eSize = hhSize;
|
||||
DISPLAYLEVEL(1, "HUF_writeCTable error \n");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ################################################################
|
||||
# Copyright (c) Yann Collet, Facebook, Inc.
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -242,6 +242,13 @@ MEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size
|
||||
frameSizeInfo.compressedSize = ERROR(srcSize_wrong);
|
||||
frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
/* In all cases, decompressedBound == nbBlocks * ZSTD_BLOCKSIZE_MAX.
|
||||
* So we can compute nbBlocks without having to change every function.
|
||||
*/
|
||||
if (frameSizeInfo.decompressedBound != ZSTD_CONTENTSIZE_ERROR) {
|
||||
assert((frameSizeInfo.decompressedBound & (ZSTD_BLOCKSIZE_MAX - 1)) == 0);
|
||||
frameSizeInfo.nbBlocks = (size_t)(frameSizeInfo.decompressedBound / ZSTD_BLOCKSIZE_MAX);
|
||||
}
|
||||
return frameSizeInfo;
|
||||
}
|
||||
|
||||
|
||||
+15
-48
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -190,25 +190,6 @@ typedef signed long long S64;
|
||||
/****************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* FSE_FORCE_MEMORY_ACCESS
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets generating assembly depending on alignment.
|
||||
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef FSE_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define FSE_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned FSE_32bits(void)
|
||||
{
|
||||
@@ -221,24 +202,6 @@ static unsigned FSE_isLittleEndian(void)
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(FSE_FORCE_MEMORY_ACCESS) && (FSE_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
static U16 FSE_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
static U32 FSE_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
static U64 FSE_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
#elif defined(FSE_FORCE_MEMORY_ACCESS) && (FSE_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
|
||||
|
||||
static U16 FSE_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
static U32 FSE_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
static U64 FSE_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
#else
|
||||
|
||||
static U16 FSE_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
@@ -254,8 +217,6 @@ static U64 FSE_read64(const void* memPtr)
|
||||
U64 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
}
|
||||
|
||||
#endif /* FSE_FORCE_MEMORY_ACCESS */
|
||||
|
||||
static U16 FSE_readLE16(const void* memPtr)
|
||||
{
|
||||
if (FSE_isLittleEndian())
|
||||
@@ -1190,7 +1151,7 @@ static size_t HUF_decompress (void* dst, size_t maxDstSize, const void* cSrc, si
|
||||
zstd - standard compression library
|
||||
Copyright (C) 2014-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1759,20 +1720,26 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
|
||||
static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11}; /* subtracted */
|
||||
const BYTE* const ostart = op;
|
||||
BYTE* const oLitEnd = op + sequence.litLength;
|
||||
const size_t litLength = sequence.litLength;
|
||||
BYTE* const endMatch = op + litLength + sequence.matchLength; /* risk : address space overflow (32-bits) */
|
||||
const BYTE* const litEnd = *litPtr + litLength;
|
||||
|
||||
/* check */
|
||||
/* checks */
|
||||
size_t const seqLength = sequence.litLength + sequence.matchLength;
|
||||
|
||||
if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);
|
||||
/* Now we know there are no overflow in literal nor match lengths, can use pointer checks */
|
||||
if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);
|
||||
|
||||
if (endMatch > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected);
|
||||
if (sequence.matchLength > (size_t)(*litPtr-op)) return ERROR(dstSize_tooSmall); /* overwrite literal segment */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected); /* overRead beyond lit buffer */
|
||||
if (sequence.matchLength > (size_t)(*litPtr-op)) return ERROR(dstSize_tooSmall); /* overwrite literal segment */
|
||||
|
||||
/* copy Literals */
|
||||
if (((size_t)(*litPtr - op) < 8) || ((size_t)(oend-litEnd) < 8) || (op+litLength > oend-8))
|
||||
memmove(op, *litPtr, litLength); /* overwrite risk */
|
||||
else
|
||||
ZSTD_wildcopy(op, *litPtr, litLength);
|
||||
ZSTD_memmove(op, *litPtr, sequence.litLength); /* note : v0.1 seems to allow scenarios where output or input are close to end of buffer */
|
||||
|
||||
op += litLength;
|
||||
*litPtr = litEnd; /* update for next sequence */
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+20
-61
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -28,7 +28,7 @@
|
||||
low-level memory access routines
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -115,24 +115,6 @@ extern "C" {
|
||||
/****************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets generating assembly depending on alignment.
|
||||
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }
|
||||
@@ -143,33 +125,6 @@ MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
/* violates C standard on structure alignment.
|
||||
Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
|
||||
#else
|
||||
|
||||
/* default method, safe and standard.
|
||||
can sometimes prove slower */
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
@@ -190,9 +145,6 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value)
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
#endif /* MEM_FORCE_MEMORY_ACCESS */
|
||||
|
||||
|
||||
MEM_STATIC U16 MEM_readLE16(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -269,7 +221,7 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -510,7 +462,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
||||
Error codes and messages
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -609,7 +561,7 @@ typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be mor
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -753,7 +705,7 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -822,7 +774,7 @@ static size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, si
|
||||
Header File
|
||||
Copyright (C) 2014-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -882,7 +834,7 @@ typedef struct ZSTD_CCtx_s ZSTD_CCtx; /* incomplete type */
|
||||
Header File for static linking only
|
||||
Copyright (C) 2014-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -946,7 +898,7 @@ typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||
FSE : Finite State Entropy coder
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1450,7 +1402,7 @@ static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, siz
|
||||
Huff0 : Huffman coder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2609,7 +2561,7 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
|
||||
zstd - standard compression library
|
||||
Copyright (C) 2014-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -3114,12 +3066,19 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
const BYTE* const litEnd = *litPtr + sequence.litLength;
|
||||
|
||||
/* checks */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
|
||||
size_t const seqLength = sequence.litLength + sequence.matchLength;
|
||||
|
||||
if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);
|
||||
/* Now we know there are no overflow in literal nor match lengths, can use the pointer check */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);
|
||||
|
||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected); /* overRead beyond lit buffer */
|
||||
|
||||
/* copy Literals */
|
||||
ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
op = oLitEnd;
|
||||
*litPtr = litEnd; /* update for next sequence */
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+21
-64
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -29,7 +29,7 @@
|
||||
low-level memory access routines
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -116,24 +116,6 @@ extern "C" {
|
||||
/****************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets generating assembly depending on alignment.
|
||||
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }
|
||||
@@ -144,33 +126,6 @@ MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
/* violates C standard on structure alignment.
|
||||
Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
|
||||
#else
|
||||
|
||||
/* default method, safe and standard.
|
||||
can sometimes prove slower */
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
@@ -191,10 +146,6 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value)
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
|
||||
#endif /* MEM_FORCE_MEMORY_ACCESS */
|
||||
|
||||
|
||||
MEM_STATIC U16 MEM_readLE16(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -271,7 +222,7 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -512,7 +463,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
||||
Error codes and messages
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -611,7 +562,7 @@ typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be mor
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -755,7 +706,7 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -823,7 +774,7 @@ static size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, si
|
||||
Header File
|
||||
Copyright (C) 2014-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -883,7 +834,7 @@ typedef struct ZSTD_CCtx_s ZSTD_CCtx; /* incomplete type */
|
||||
Header File for static linking only
|
||||
Copyright (C) 2014-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -947,7 +898,7 @@ typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||
FSE : Finite State Entropy coder
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1451,7 +1402,7 @@ static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, siz
|
||||
Huff0 : Huffman coder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2248,7 +2199,7 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
|
||||
zstd - standard compression library
|
||||
Copyright (C) 2014-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2755,18 +2706,24 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
const BYTE* const litEnd = *litPtr + sequence.litLength;
|
||||
|
||||
/* checks */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
|
||||
size_t const seqLength = sequence.litLength + sequence.matchLength;
|
||||
|
||||
if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);
|
||||
/* Now we know there are no overflow in literal nor match lengths, can use pointer checks */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);
|
||||
|
||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected); /* overRead beyond lit buffer */
|
||||
|
||||
/* copy Literals */
|
||||
ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
op = oLitEnd;
|
||||
*litPtr = litEnd; /* update for next sequence */
|
||||
|
||||
/* copy Match */
|
||||
{
|
||||
const BYTE* match = op - sequence.offset;
|
||||
{ const BYTE* match = op - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if (sequence.offset > (size_t)op) return ERROR(corruption_detected); /* address space overflow test (this test seems kept by clang optimizer) */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+19
-61
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -87,24 +87,6 @@ extern "C" {
|
||||
/****************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets generating assembly depending on alignment.
|
||||
* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }
|
||||
@@ -115,33 +97,6 @@ MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
/* violates C standard on structure alignment.
|
||||
Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
|
||||
#else
|
||||
|
||||
/* default method, safe and standard.
|
||||
can sometimes prove slower */
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
@@ -162,9 +117,6 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value)
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
#endif /* MEM_FORCE_MEMORY_ACCESS */
|
||||
|
||||
|
||||
MEM_STATIC U16 MEM_readLE16(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -542,7 +494,7 @@ If there is an error, the function will return an error code, which can be teste
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -781,7 +733,7 @@ MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -930,7 +882,7 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
|
||||
FSE : Finite State Entropy coder
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1436,7 +1388,7 @@ static size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, siz
|
||||
header file
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1514,7 +1466,7 @@ static unsigned HUF_isError(size_t code); /* tells if a return value i
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1601,7 +1553,7 @@ static size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const
|
||||
Huff0 : Huffman coder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2401,7 +2353,7 @@ static size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_
|
||||
zstd - decompression module fo v0.4 legacy format
|
||||
Copyright (C) 2015-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2876,13 +2828,19 @@ static size_t ZSTD_execSequence(BYTE* op,
|
||||
const BYTE* const litEnd = *litPtr + sequence.litLength;
|
||||
const BYTE* match = oLitEnd - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
|
||||
/* checks */
|
||||
size_t const seqLength = sequence.litLength + sequence.matchLength;
|
||||
|
||||
if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);
|
||||
/* Now we know there are no overflow in literal nor match lengths, can use pointer checks */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);
|
||||
|
||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected); /* risk read beyond lit buffer */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected); /* overRead beyond lit buffer */
|
||||
|
||||
/* copy Literals */
|
||||
ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
op = oLitEnd;
|
||||
*litPtr = litEnd; /* update for next sequence */
|
||||
|
||||
@@ -3283,7 +3241,7 @@ static void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* dict, s
|
||||
Buffered version of Zstd compression library
|
||||
Copyright (C) 2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+24
-70
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -19,7 +19,7 @@
|
||||
low-level memory access routines
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -106,24 +106,6 @@ extern "C" {
|
||||
/*-**************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS :
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets depending on alignment.
|
||||
* In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }
|
||||
@@ -134,37 +116,6 @@ MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
/* violates C standard, by lying on structure alignment.
|
||||
Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
|
||||
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
MEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }
|
||||
MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }
|
||||
|
||||
#else
|
||||
|
||||
/* default method, safe and standard.
|
||||
can sometimes prove slower */
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
@@ -195,9 +146,6 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value)
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
#endif /* MEM_FORCE_MEMORY_ACCESS */
|
||||
|
||||
|
||||
MEM_STATIC U16 MEM_readLE16(const void* memPtr)
|
||||
{
|
||||
if (MEM_isLittleEndian())
|
||||
@@ -262,7 +210,7 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
Header File for static linking only
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -286,7 +234,7 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net
|
||||
- zstd homepage : https://facebook.github.io/zstd
|
||||
*/
|
||||
#ifndef ZSTD_STATIC_H
|
||||
#define ZSTD_STATIC_H
|
||||
@@ -398,7 +346,7 @@ size_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity
|
||||
Header File for include
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -553,7 +501,7 @@ typedef struct {
|
||||
header file
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -672,7 +620,7 @@ size_t FSEv05_decompress_usingDTable(void* dst, size_t dstCapacity, const void*
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -901,7 +849,7 @@ MEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* DStream)
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1051,7 +999,7 @@ MEM_STATIC unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr)
|
||||
FSEv05 : Finite State Entropy coder
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1537,7 +1485,7 @@ size_t FSEv05_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t
|
||||
header file
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1610,7 +1558,7 @@ const char* HUFv05_getErrorName(size_t code); /* provides error code string (u
|
||||
header file, for static linking only
|
||||
Copyright (C) 2013-2016, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1702,7 +1650,7 @@ size_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void
|
||||
Huff0 : Huffman coder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2547,7 +2495,7 @@ size_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||
zstd - standard compression library
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -3234,13 +3182,19 @@ static size_t ZSTDv05_execSequence(BYTE* op,
|
||||
const BYTE* const litEnd = *litPtr + sequence.litLength;
|
||||
const BYTE* match = oLitEnd - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
|
||||
/* checks */
|
||||
size_t const seqLength = sequence.litLength + sequence.matchLength;
|
||||
|
||||
if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);
|
||||
/* Now we know there are no overflow in literal nor match lengths, can use pointer checks */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);
|
||||
|
||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected); /* risk read beyond lit buffer */
|
||||
if (litEnd > litLimit) return ERROR(corruption_detected); /* overRead beyond lit buffer */
|
||||
|
||||
/* copy Literals */
|
||||
ZSTDv05_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
ZSTDv05_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
op = oLitEnd;
|
||||
*litPtr = litEnd; /* update for next sequence */
|
||||
|
||||
@@ -3746,7 +3700,7 @@ size_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, s
|
||||
Buffered version of Zstd compression library
|
||||
Copyright (C) 2015-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+31
-72
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -23,7 +23,7 @@
|
||||
low-level memory access routines
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -108,24 +108,6 @@ extern "C" {
|
||||
/*-**************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS :
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets depending on alignment.
|
||||
* In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
|
||||
@@ -136,33 +118,6 @@ MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
/* violates C standard, by lying on structure alignment.
|
||||
Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
|
||||
#else
|
||||
|
||||
/* default method, safe and standard.
|
||||
can sometimes prove slower */
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
@@ -183,9 +138,6 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value)
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
|
||||
#endif /* MEM_FORCE_MEMORY_ACCESS */
|
||||
|
||||
MEM_STATIC U32 MEM_swap32(U32 in)
|
||||
{
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
@@ -281,7 +233,7 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
Header File for static linking only
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -305,7 +257,7 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net
|
||||
- zstd homepage : https://facebook.github.io/zstd
|
||||
*/
|
||||
#ifndef ZSTDv06_STATIC_H
|
||||
#define ZSTDv06_STATIC_H
|
||||
@@ -412,7 +364,7 @@ ZSTDLIBv06_API size_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx, void* dst, siz
|
||||
Header File for include
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -619,7 +571,7 @@ void ZSTDv06_seqToCodes(const seqStore_t* seqStorePtr, size_t const nbSeq);
|
||||
Public Prototypes declaration
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -767,7 +719,7 @@ If there is an error, the function will return an error code, which can be teste
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1002,7 +954,7 @@ MEM_STATIC unsigned BITv06_endOfDStream(const BITv06_DStream_t* DStream)
|
||||
header file for static linking (only)
|
||||
Copyright (C) 2013-2015, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1210,7 +1162,7 @@ MEM_STATIC BYTE FSEv06_decodeSymbolFast(FSEv06_DState_t* DStatePtr, BITv06_DStre
|
||||
Common functions of New Generation Entropy library
|
||||
Copyright (C) 2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1355,7 +1307,7 @@ size_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned
|
||||
FSE : Finite State Entropy decoder
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1679,7 +1631,7 @@ size_t FSEv06_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t
|
||||
header file
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1749,7 +1701,7 @@ size_t HUFv06_compressBound(size_t size); /**< maximum compressed size */
|
||||
header file, for static linking only
|
||||
Copyright (C) 2013-2016, Yann Collet
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1931,7 +1883,7 @@ MEM_STATIC size_t HUFv06_readStats(BYTE* huffWeight, size_t hwSize, U32* rankSta
|
||||
Huffman decoder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2676,7 +2628,7 @@ size_t HUFv06_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||
Common functions of Zstd compression library
|
||||
Copyright (C) 2015-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2700,7 +2652,7 @@ size_t HUFv06_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cS
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net/
|
||||
- zstd homepage : https://facebook.github.io/zstd/
|
||||
*/
|
||||
|
||||
|
||||
@@ -2730,7 +2682,7 @@ const char* ZBUFFv06_getErrorName(size_t errorCode) { return ERR_getErrorName(er
|
||||
zstd - standard compression library
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2754,7 +2706,7 @@ const char* ZBUFFv06_getErrorName(size_t errorCode) { return ERR_getErrorName(er
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net
|
||||
- zstd homepage : https://facebook.github.io/zstd
|
||||
*/
|
||||
|
||||
/* ***************************************************************
|
||||
@@ -3370,13 +3322,19 @@ static size_t ZSTDv06_execSequence(BYTE* op,
|
||||
const BYTE* const iLitEnd = *litPtr + sequence.litLength;
|
||||
const BYTE* match = oLitEnd - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
|
||||
/* checks */
|
||||
size_t const seqLength = sequence.litLength + sequence.matchLength;
|
||||
|
||||
if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);
|
||||
/* Now we know there are no overflow in literal nor match lengths, can use pointer checks */
|
||||
if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);
|
||||
|
||||
if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
|
||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* overRead beyond lit buffer */
|
||||
|
||||
/* copy Literals */
|
||||
ZSTDv06_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
ZSTDv06_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
|
||||
op = oLitEnd;
|
||||
*litPtr = iLitEnd; /* update for next sequence */
|
||||
|
||||
@@ -3889,7 +3847,7 @@ size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, s
|
||||
Buffered version of Zstd compression library
|
||||
Copyright (C) 2015-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -3913,7 +3871,7 @@ size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, s
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net/
|
||||
- zstd homepage : https://facebook.github.io/zstd/
|
||||
*/
|
||||
|
||||
|
||||
@@ -4035,7 +3993,8 @@ size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* zbd,
|
||||
size_t const toLoad = hSize - zbd->lhSize; /* if hSize!=0, hSize > zbd->lhSize */
|
||||
if (ZSTDv06_isError(hSize)) return hSize;
|
||||
if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */
|
||||
memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);
|
||||
if (ip != NULL)
|
||||
memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);
|
||||
zbd->lhSize += iend-ip;
|
||||
*dstCapacityPtr = 0;
|
||||
return (hSize - zbd->lhSize) + ZSTDv06_blockHeaderSize; /* remaining header bytes + next block header */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+24
-67
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -184,7 +184,7 @@ ZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockS
|
||||
low-level memory access routines
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -268,24 +268,6 @@ extern "C" {
|
||||
/*-**************************************************************
|
||||
* Memory I/O
|
||||
*****************************************************************/
|
||||
/* MEM_FORCE_MEMORY_ACCESS :
|
||||
* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
|
||||
* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
|
||||
* The below switch allow to select different access method for improved performance.
|
||||
* Method 0 (default) : use `memcpy()`. Safe and portable.
|
||||
* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
|
||||
* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
|
||||
* Method 2 : direct access. This method is portable but violate C standard.
|
||||
* It can generate buggy code on targets depending on alignment.
|
||||
* In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
|
||||
* See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.
|
||||
* Prefer these methods in priority order (0 > 1 > 2)
|
||||
*/
|
||||
#ifndef MEM_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
|
||||
# if defined(__INTEL_COMPILER) || defined(__GNUC__) || defined(__ICCARM__)
|
||||
# define MEM_FORCE_MEMORY_ACCESS 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
MEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }
|
||||
MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
|
||||
@@ -296,33 +278,6 @@ MEM_STATIC unsigned MEM_isLittleEndian(void)
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
|
||||
|
||||
/* violates C standard, by lying on structure alignment.
|
||||
Only use if no other choice to achieve best performance on target platform */
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }
|
||||
MEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }
|
||||
MEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
|
||||
|
||||
#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)
|
||||
|
||||
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
|
||||
/* currently only defined for gcc and icc */
|
||||
typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }
|
||||
MEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
|
||||
MEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
|
||||
|
||||
MEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }
|
||||
|
||||
#else
|
||||
|
||||
/* default method, safe and standard.
|
||||
can sometimes prove slower */
|
||||
|
||||
MEM_STATIC U16 MEM_read16(const void* memPtr)
|
||||
{
|
||||
U16 val; memcpy(&val, memPtr, sizeof(val)); return val;
|
||||
@@ -343,8 +298,6 @@ MEM_STATIC void MEM_write16(void* memPtr, U16 value)
|
||||
memcpy(memPtr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
#endif /* MEM_FORCE_MEMORY_ACCESS */
|
||||
|
||||
MEM_STATIC U32 MEM_swap32(U32 in)
|
||||
{
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
@@ -439,7 +392,7 @@ MEM_STATIC size_t MEM_readLEST(const void* memPtr)
|
||||
header file (to include)
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -670,7 +623,7 @@ MEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* DStream)
|
||||
Public Prototypes declaration
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -978,7 +931,7 @@ MEM_STATIC BYTE FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStre
|
||||
header file
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1151,7 +1104,7 @@ size_t HUFv07_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void
|
||||
Common functions of New Generation Entropy library
|
||||
Copyright (C) 2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1375,7 +1328,7 @@ size_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
|
||||
FSE : Finite State Entropy decoder
|
||||
Copyright (C) 2013-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -1699,7 +1652,7 @@ size_t FSEv07_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t
|
||||
Huffman decoder, part of New Generation Entropy library
|
||||
Copyright (C) 2013-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2577,7 +2530,7 @@ size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize,
|
||||
Common functions of Zstd compression library
|
||||
Copyright (C) 2015-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2601,7 +2554,7 @@ size_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize,
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net/
|
||||
- zstd homepage : https://facebook.github.io/zstd/
|
||||
*/
|
||||
|
||||
|
||||
@@ -2647,7 +2600,7 @@ static void ZSTDv07_defaultFreeFunction(void* opaque, void* address)
|
||||
Header File for include
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2854,7 +2807,7 @@ static const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction
|
||||
zstd - standard compression library
|
||||
Copyright (C) 2014-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -2878,7 +2831,7 @@ static const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net
|
||||
- zstd homepage : https://facebook.github.io/zstd
|
||||
*/
|
||||
|
||||
/* ***************************************************************
|
||||
@@ -3599,11 +3552,14 @@ size_t ZSTDv07_execSequence(BYTE* op,
|
||||
const BYTE* match = oLitEnd - sequence.offset;
|
||||
|
||||
/* check */
|
||||
if ((oLitEnd>oend_w) | (oMatchEnd>oend)) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
|
||||
if (iLitEnd > litLimit) return ERROR(corruption_detected); /* over-read beyond lit buffer */
|
||||
assert(oend >= op);
|
||||
if (sequence.litLength + WILDCOPY_OVERLENGTH > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
if (sequenceLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);
|
||||
assert(litLimit >= *litPtr);
|
||||
if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);;
|
||||
|
||||
/* copy Literals */
|
||||
ZSTDv07_wildcopy(op, *litPtr, sequence.litLength); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
||||
ZSTDv07_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
|
||||
op = oLitEnd;
|
||||
*litPtr = iLitEnd; /* update for next sequence */
|
||||
|
||||
@@ -3617,7 +3573,7 @@ size_t ZSTDv07_execSequence(BYTE* op,
|
||||
return sequenceLength;
|
||||
}
|
||||
/* span extDict & currentPrefixSegment */
|
||||
{ size_t const length1 = dictEnd - match;
|
||||
{ size_t const length1 = (size_t)(dictEnd - match);
|
||||
memmove(oLitEnd, match, length1);
|
||||
op = oLitEnd + length1;
|
||||
sequence.matchLength -= length1;
|
||||
@@ -4253,7 +4209,7 @@ ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
|
||||
Buffered version of Zstd compression library
|
||||
Copyright (C) 2015-2016, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
@@ -4277,7 +4233,7 @@ ZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- zstd homepage : http://www.zstd.net/
|
||||
- zstd homepage : https://facebook.github.io/zstd/
|
||||
*/
|
||||
|
||||
|
||||
@@ -4417,7 +4373,8 @@ size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* zbd,
|
||||
if (hSize != 0) {
|
||||
size_t const toLoad = hSize - zbd->lhSize; /* if hSize!=0, hSize > zbd->lhSize */
|
||||
if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */
|
||||
memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);
|
||||
if (ip != NULL)
|
||||
memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);
|
||||
zbd->lhSize += iend-ip;
|
||||
*dstCapacityPtr = 0;
|
||||
return (hSize - zbd->lhSize) + ZSTDv07_blockHeaderSize; /* remaining header bytes + next block header */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
|
||||
+25
-17
@@ -1,5 +1,5 @@
|
||||
# ################################################################
|
||||
# Copyright (c) Yann Collet, Facebook, Inc.
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# All rights reserved.
|
||||
#
|
||||
# This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -15,17 +15,34 @@
|
||||
# Zstd lib directory
|
||||
LIBZSTD ?= ./
|
||||
|
||||
# ZSTD_LIB_MINIFY is a helper variable that
|
||||
# configures a bunch of other variables to space-optimized defaults.
|
||||
ZSTD_LIB_MINIFY ?= 0
|
||||
|
||||
# Legacy support
|
||||
ZSTD_LEGACY_SUPPORT ?= 5
|
||||
ifneq ($(ZSTD_LIB_MINIFY), 0)
|
||||
ZSTD_LEGACY_SUPPORT ?= 0
|
||||
else
|
||||
ZSTD_LEGACY_SUPPORT ?= 5
|
||||
endif
|
||||
ZSTD_LEGACY_MULTITHREADED_API ?= 0
|
||||
|
||||
# Build size optimizations
|
||||
HUF_FORCE_DECOMPRESS_X1 ?= 0
|
||||
HUF_FORCE_DECOMPRESS_X2 ?= 0
|
||||
ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT ?= 0
|
||||
ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG ?= 0
|
||||
ZSTD_NO_INLINE ?= 0
|
||||
ZSTD_STRIP_ERROR_STRINGS ?= 0
|
||||
ifneq ($(ZSTD_LIB_MINIFY), 0)
|
||||
HUF_FORCE_DECOMPRESS_X1 ?= 1
|
||||
HUF_FORCE_DECOMPRESS_X2 ?= 0
|
||||
ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT ?= 1
|
||||
ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG ?= 0
|
||||
ZSTD_NO_INLINE ?= 1
|
||||
ZSTD_STRIP_ERROR_STRINGS ?= 1
|
||||
else
|
||||
HUF_FORCE_DECOMPRESS_X1 ?= 0
|
||||
HUF_FORCE_DECOMPRESS_X2 ?= 0
|
||||
ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT ?= 0
|
||||
ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG ?= 0
|
||||
ZSTD_NO_INLINE ?= 0
|
||||
ZSTD_STRIP_ERROR_STRINGS ?= 0
|
||||
endif
|
||||
|
||||
# Assembly support
|
||||
ZSTD_NO_ASM ?= 0
|
||||
@@ -61,17 +78,8 @@ LIBVER := $(shell echo $(LIBVER_SCRIPT))
|
||||
CCVER := $(shell $(CC) --version)
|
||||
ZSTD_VERSION?= $(LIBVER)
|
||||
|
||||
# ZSTD_LIB_MINIFY is a helper variable that
|
||||
# configures a bunch of other variables to space-optimized defaults.
|
||||
ZSTD_LIB_MINIFY ?= 0
|
||||
ifneq ($(ZSTD_LIB_MINIFY), 0)
|
||||
HAVE_CC_OZ ?= $(shell echo "" | $(CC) -Oz -x c -c - -o /dev/null 2> /dev/null && echo 1 || echo 0)
|
||||
ZSTD_LEGACY_SUPPORT ?= 0
|
||||
ZSTD_LIB_DEPRECATED ?= 0
|
||||
HUF_FORCE_DECOMPRESS_X1 ?= 1
|
||||
ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT ?= 1
|
||||
ZSTD_NO_INLINE ?= 1
|
||||
ZSTD_STRIP_ERROR_STRINGS ?= 1
|
||||
ifneq ($(HAVE_CC_OZ), 0)
|
||||
# Some compilers (clang) support an even more space-optimized setting.
|
||||
CFLAGS += -Oz
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
# ZSTD - standard compression algorithm
|
||||
# Copyright (C) 2014-2016, Yann Collet, Facebook
|
||||
# BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
# BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)
|
||||
|
||||
prefix=@PREFIX@
|
||||
exec_prefix=@EXEC_PREFIX@
|
||||
@@ -9,7 +9,7 @@ libdir=@LIBDIR@
|
||||
|
||||
Name: zstd
|
||||
Description: fast lossless compression algorithm library
|
||||
URL: http://www.zstd.net/
|
||||
URL: https://facebook.github.io/zstd/
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lzstd
|
||||
Libs.private: @LIBS_PRIVATE@
|
||||
|
||||
+13
-3
@@ -1,17 +1,27 @@
|
||||
module libzstd [extern_c] {
|
||||
header "zstd.h"
|
||||
export *
|
||||
config_macros [exhaustive] /* zstd.h */ \
|
||||
config_macros [exhaustive] \
|
||||
/* zstd.h */ \
|
||||
ZSTD_STATIC_LINKING_ONLY, \
|
||||
ZSTDLIB_VISIBILITY, \
|
||||
ZSTDLIB_VISIBLE, \
|
||||
ZSTDLIB_HIDDEN, \
|
||||
ZSTD_DLL_EXPORT, \
|
||||
ZSTDLIB_STATIC_API, \
|
||||
ZSTD_DISABLE_DEPRECATE_WARNINGS, \
|
||||
ZSTD_CLEVEL_DEFAULT, \
|
||||
/* zdict.h */ ZDICT_STATIC_LINKING_ONLY, \
|
||||
/* zdict.h */ \
|
||||
ZDICT_STATIC_LINKING_ONLY, \
|
||||
ZDICTLIB_VISIBLE, \
|
||||
ZDICTLIB_HIDDEN, \
|
||||
ZDICTLIB_VISIBILITY, \
|
||||
ZDICTLIB_STATIC_API, \
|
||||
ZDICT_DISABLE_DEPRECATE_WARNINGS, \
|
||||
/* zstd_errors.h */ ZSTDERRORLIB_VISIBILITY
|
||||
/* zstd_errors.h */ \
|
||||
ZSTDERRORLIB_VISIBLE, \
|
||||
ZSTDERRORLIB_HIDDEN, \
|
||||
ZSTDERRORLIB_VISIBILITY
|
||||
|
||||
module dictbuilder [extern_c] {
|
||||
header "zdict.h"
|
||||
|
||||
+51
-29
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -8,32 +8,43 @@
|
||||
* You may select, at your option, one of the above-listed licenses.
|
||||
*/
|
||||
|
||||
#ifndef DICTBUILDER_H_001
|
||||
#define DICTBUILDER_H_001
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef ZSTD_ZDICT_H
|
||||
#define ZSTD_ZDICT_H
|
||||
|
||||
/*====== Dependencies ======*/
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/* ===== ZDICTLIB_API : control library symbols visibility ===== */
|
||||
#ifndef ZDICTLIB_VISIBILITY
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define ZDICTLIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||
#ifndef ZDICTLIB_VISIBLE
|
||||
/* Backwards compatibility with old macro name */
|
||||
# ifdef ZDICTLIB_VISIBILITY
|
||||
# define ZDICTLIB_VISIBLE ZDICTLIB_VISIBILITY
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZDICTLIB_VISIBLE __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define ZDICTLIB_VISIBILITY
|
||||
# define ZDICTLIB_VISIBLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZDICTLIB_HIDDEN
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZDICTLIB_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
# else
|
||||
# define ZDICTLIB_HIDDEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||
# define ZDICTLIB_API __declspec(dllexport) ZDICTLIB_VISIBILITY
|
||||
# define ZDICTLIB_API __declspec(dllexport) ZDICTLIB_VISIBLE
|
||||
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||
# define ZDICTLIB_API __declspec(dllimport) ZDICTLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
# define ZDICTLIB_API __declspec(dllimport) ZDICTLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define ZDICTLIB_API ZDICTLIB_VISIBILITY
|
||||
# define ZDICTLIB_API ZDICTLIB_VISIBLE
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -201,9 +212,9 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer(void* dictBuffer, size_t dictBufferCap
|
||||
const size_t* samplesSizes, unsigned nbSamples);
|
||||
|
||||
typedef struct {
|
||||
int compressionLevel; /*< optimize for a specific zstd compression level; 0 means default */
|
||||
unsigned notificationLevel; /*< Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */
|
||||
unsigned dictID; /*< force dictID value; 0 means auto mode (32-bits random value)
|
||||
int compressionLevel; /**< optimize for a specific zstd compression level; 0 means default */
|
||||
unsigned notificationLevel; /**< Write log to stderr; 0 = none (default); 1 = errors; 2 = progression; 3 = details; 4 = debug; */
|
||||
unsigned dictID; /**< force dictID value; 0 means auto mode (32-bits random value)
|
||||
* NOTE: The zstd format reserves some dictionary IDs for future use.
|
||||
* You may use them in private settings, but be warned that they
|
||||
* may be used by zstd in a public dictionary registry in the future.
|
||||
@@ -260,9 +271,21 @@ ZDICTLIB_API size_t ZDICT_getDictHeaderSize(const void* dictBuffer, size_t dictS
|
||||
ZDICTLIB_API unsigned ZDICT_isError(size_t errorCode);
|
||||
ZDICTLIB_API const char* ZDICT_getErrorName(size_t errorCode);
|
||||
|
||||
#endif /* ZSTD_ZDICT_H */
|
||||
|
||||
#if defined(ZDICT_STATIC_LINKING_ONLY) && !defined(ZSTD_ZDICT_H_STATIC)
|
||||
#define ZSTD_ZDICT_H_STATIC
|
||||
|
||||
#ifdef ZDICT_STATIC_LINKING_ONLY
|
||||
/* This can be overridden externally to hide static symbols. */
|
||||
#ifndef ZDICTLIB_STATIC_API
|
||||
# if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||
# define ZDICTLIB_STATIC_API __declspec(dllexport) ZDICTLIB_VISIBLE
|
||||
# elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||
# define ZDICTLIB_STATIC_API __declspec(dllimport) ZDICTLIB_VISIBLE
|
||||
# else
|
||||
# define ZDICTLIB_STATIC_API ZDICTLIB_VISIBLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* ====================================================================================
|
||||
* The definitions in this section are considered experimental.
|
||||
@@ -318,7 +341,7 @@ typedef struct {
|
||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||
* It's recommended that total size of all samples be about ~x100 times the target size of dictionary.
|
||||
*/
|
||||
ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
|
||||
ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_cover(
|
||||
void *dictBuffer, size_t dictBufferCapacity,
|
||||
const void *samplesBuffer, const size_t *samplesSizes, unsigned nbSamples,
|
||||
ZDICT_cover_params_t parameters);
|
||||
@@ -340,7 +363,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_cover(
|
||||
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||
* Note: ZDICT_optimizeTrainFromBuffer_cover() requires about 8 bytes of memory for each input byte and additionally another 5 bytes of memory for each byte of memory for each thread.
|
||||
*/
|
||||
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
void* dictBuffer, size_t dictBufferCapacity,
|
||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||
ZDICT_cover_params_t* parameters);
|
||||
@@ -361,7 +384,7 @@ ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_cover(
|
||||
* In general, it's recommended to provide a few thousands samples, though this can vary a lot.
|
||||
* It's recommended that total size of all samples be about ~x100 times the target size of dictionary.
|
||||
*/
|
||||
ZDICTLIB_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer,
|
||||
ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer,
|
||||
size_t dictBufferCapacity, const void *samplesBuffer,
|
||||
const size_t *samplesSizes, unsigned nbSamples,
|
||||
ZDICT_fastCover_params_t parameters);
|
||||
@@ -384,7 +407,7 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_fastCover(void *dictBuffer,
|
||||
* See ZDICT_trainFromBuffer() for details on failure modes.
|
||||
* Note: ZDICT_optimizeTrainFromBuffer_fastCover() requires about 6 * 2^f bytes of memory for each thread.
|
||||
*/
|
||||
ZDICTLIB_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
|
||||
ZDICTLIB_STATIC_API size_t ZDICT_optimizeTrainFromBuffer_fastCover(void* dictBuffer,
|
||||
size_t dictBufferCapacity, const void* samplesBuffer,
|
||||
const size_t* samplesSizes, unsigned nbSamples,
|
||||
ZDICT_fastCover_params_t* parameters);
|
||||
@@ -409,7 +432,7 @@ typedef struct {
|
||||
* It's recommended that total size of all samples be about ~x100 times the target size of dictionary.
|
||||
* Note: ZDICT_trainFromBuffer_legacy() will send notifications into stderr if instructed to, using notificationLevel>0.
|
||||
*/
|
||||
ZDICTLIB_API size_t ZDICT_trainFromBuffer_legacy(
|
||||
ZDICTLIB_STATIC_API size_t ZDICT_trainFromBuffer_legacy(
|
||||
void* dictBuffer, size_t dictBufferCapacity,
|
||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples,
|
||||
ZDICT_legacy_params_t parameters);
|
||||
@@ -421,32 +444,31 @@ ZDICTLIB_API size_t ZDICT_trainFromBuffer_legacy(
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||
Otherwise, it's also possible to manually define ZDICT_DISABLE_DEPRECATE_WARNINGS */
|
||||
#ifdef ZDICT_DISABLE_DEPRECATE_WARNINGS
|
||||
# define ZDICT_DEPRECATED(message) ZDICTLIB_API /* disable deprecation warnings */
|
||||
# define ZDICT_DEPRECATED(message) /* disable deprecation warnings */
|
||||
#else
|
||||
# define ZDICT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||
# define ZDICT_DEPRECATED(message) [[deprecated(message)]] ZDICTLIB_API
|
||||
# define ZDICT_DEPRECATED(message) [[deprecated(message)]]
|
||||
# elif defined(__clang__) || (ZDICT_GCC_VERSION >= 405)
|
||||
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated(message)))
|
||||
# define ZDICT_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (ZDICT_GCC_VERSION >= 301)
|
||||
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __attribute__((deprecated))
|
||||
# define ZDICT_DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define ZDICT_DEPRECATED(message) ZDICTLIB_API __declspec(deprecated(message))
|
||||
# define ZDICT_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement ZDICT_DEPRECATED for this compiler")
|
||||
# define ZDICT_DEPRECATED(message) ZDICTLIB_API
|
||||
# define ZDICT_DEPRECATED(message)
|
||||
# endif
|
||||
#endif /* ZDICT_DISABLE_DEPRECATE_WARNINGS */
|
||||
|
||||
ZDICT_DEPRECATED("use ZDICT_finalizeDictionary() instead")
|
||||
ZDICTLIB_STATIC_API
|
||||
size_t ZDICT_addEntropyTablesFromBuffer(void* dictBuffer, size_t dictContentSize, size_t dictBufferCapacity,
|
||||
const void* samplesBuffer, const size_t* samplesSizes, unsigned nbSamples);
|
||||
|
||||
|
||||
#endif /* ZDICT_STATIC_LINKING_ONLY */
|
||||
#endif /* ZSTD_ZDICT_H_STATIC */
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DICTBUILDER_H_001 */
|
||||
|
||||
+350
-34
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -14,21 +14,31 @@ extern "C" {
|
||||
#ifndef ZSTD_H_235446
|
||||
#define ZSTD_H_235446
|
||||
|
||||
/* ====== Dependency ======*/
|
||||
/* ====== Dependencies ======*/
|
||||
#include <limits.h> /* INT_MAX */
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/* ===== ZSTDLIB_API : control library symbols visibility ===== */
|
||||
#ifndef ZSTDLIB_VISIBLE
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
/* Backwards compatibility with old macro name */
|
||||
# ifdef ZSTDLIB_VISIBILITY
|
||||
# define ZSTDLIB_VISIBLE ZSTDLIB_VISIBILITY
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZSTDLIB_VISIBLE __attribute__ ((visibility ("default")))
|
||||
# define ZSTDLIB_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
# else
|
||||
# define ZSTDLIB_VISIBLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZSTDLIB_HIDDEN
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZSTDLIB_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
# else
|
||||
# define ZSTDLIB_HIDDEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||
# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBLE
|
||||
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||
@@ -96,7 +106,7 @@ extern "C" {
|
||||
/*------ Version ------*/
|
||||
#define ZSTD_VERSION_MAJOR 1
|
||||
#define ZSTD_VERSION_MINOR 5
|
||||
#define ZSTD_VERSION_RELEASE 3
|
||||
#define ZSTD_VERSION_RELEASE 4
|
||||
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
|
||||
|
||||
/*! ZSTD_versionNumber() :
|
||||
@@ -201,8 +211,30 @@ ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
|
||||
|
||||
|
||||
/*====== Helper functions ======*/
|
||||
#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
|
||||
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
|
||||
/* ZSTD_compressBound() :
|
||||
* maximum compressed size in worst case single-pass scenario.
|
||||
* When invoking `ZSTD_compress()` or any other one-pass compression function,
|
||||
* it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)
|
||||
* as it eliminates one potential failure scenario,
|
||||
* aka not enough room in dst buffer to write the compressed frame.
|
||||
* Note : ZSTD_compressBound() itself can fail, if @srcSize > ZSTD_MAX_INPUT_SIZE .
|
||||
* In which case, ZSTD_compressBound() will return an error code
|
||||
* which can be tested using ZSTD_isError().
|
||||
*
|
||||
* ZSTD_COMPRESSBOUND() :
|
||||
* same as ZSTD_compressBound(), but as a macro.
|
||||
* It can be used to produce constants, which can be useful for static allocation,
|
||||
* for example to size a static array on stack.
|
||||
* Will produce constant value 0 if srcSize too large.
|
||||
*/
|
||||
#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00LLU : 0xFF00FF00U)
|
||||
#define ZSTD_COMPRESSBOUND(srcSize) (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
|
||||
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
|
||||
/* ZSTD_isError() :
|
||||
* Most ZSTD_* functions returning a size_t value can be tested for error,
|
||||
* using ZSTD_isError().
|
||||
* @return 1 if error, 0 otherwise
|
||||
*/
|
||||
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 int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed, requires v1.4.0+ */
|
||||
@@ -446,6 +478,8 @@ typedef enum {
|
||||
* ZSTD_c_useBlockSplitter
|
||||
* ZSTD_c_useRowMatchFinder
|
||||
* ZSTD_c_prefetchCDictTables
|
||||
* ZSTD_c_enableMatchFinderFallback
|
||||
* ZSTD_c_maxBlockSize
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly;
|
||||
* also, the enums values themselves are unstable and can still change.
|
||||
@@ -465,7 +499,10 @@ typedef enum {
|
||||
ZSTD_c_experimentalParam13=1010,
|
||||
ZSTD_c_experimentalParam14=1011,
|
||||
ZSTD_c_experimentalParam15=1012,
|
||||
ZSTD_c_experimentalParam16=1013
|
||||
ZSTD_c_experimentalParam16=1013,
|
||||
ZSTD_c_experimentalParam17=1014,
|
||||
ZSTD_c_experimentalParam18=1015,
|
||||
ZSTD_c_experimentalParam19=1016
|
||||
} ZSTD_cParameter;
|
||||
|
||||
typedef struct {
|
||||
@@ -528,7 +565,7 @@ typedef enum {
|
||||
* They will be used to compress next frame.
|
||||
* Resetting session never fails.
|
||||
* - The parameters : changes all parameters back to "default".
|
||||
* This removes any reference to any dictionary too.
|
||||
* This also removes any reference to any dictionary or external matchfinder.
|
||||
* Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
|
||||
* otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
|
||||
* - Both : similar to resetting the session, followed by resetting parameters.
|
||||
@@ -578,13 +615,15 @@ typedef enum {
|
||||
* ZSTD_d_stableOutBuffer
|
||||
* ZSTD_d_forceIgnoreChecksum
|
||||
* ZSTD_d_refMultipleDDicts
|
||||
* ZSTD_d_disableHuffmanAssembly
|
||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||
* note : never ever use experimentalParam? names directly
|
||||
*/
|
||||
ZSTD_d_experimentalParam1=1000,
|
||||
ZSTD_d_experimentalParam2=1001,
|
||||
ZSTD_d_experimentalParam3=1002,
|
||||
ZSTD_d_experimentalParam4=1003
|
||||
ZSTD_d_experimentalParam4=1003,
|
||||
ZSTD_d_experimentalParam5=1004
|
||||
|
||||
} ZSTD_dParameter;
|
||||
|
||||
@@ -763,8 +802,6 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
|
||||
* This following is a legacy streaming API, available since v1.0+ .
|
||||
* It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().
|
||||
* It is redundant, but remains fully supported.
|
||||
* Streaming in combination with advanced parameters and dictionary compression
|
||||
* can only be used through the new API.
|
||||
******************************************************************************/
|
||||
|
||||
/*!
|
||||
@@ -773,6 +810,9 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
|
||||
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
|
||||
* ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
|
||||
* ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
|
||||
*
|
||||
* Note that ZSTD_initCStream() clears any previously set dictionary. Use the new API
|
||||
* to compress with a dictionary.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
|
||||
/*!
|
||||
@@ -990,8 +1030,9 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
* Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
|
||||
* meaning "return to no-dictionary mode".
|
||||
* Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
|
||||
* To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
|
||||
* Note 1 : Dictionary is sticky, it will be used for all future compressed frames,
|
||||
* until parameters are reset, a new dictionary is loaded, or the dictionary
|
||||
* is explicitly invalidated by loading a NULL dictionary.
|
||||
* Note 2 : Loading a dictionary involves building tables.
|
||||
* It's also a CPU consuming operation, with non-negligible impact on latency.
|
||||
* Tables are dependent on compression parameters, and for this reason,
|
||||
@@ -1004,7 +1045,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
|
||||
/*! 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 future compressed frames.
|
||||
* Note that compression parameters are enforced from within CDict,
|
||||
* and supersede any compression parameter previously set within CCtx.
|
||||
* The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
|
||||
@@ -1039,9 +1080,9 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
|
||||
const void* prefix, size_t prefixSize);
|
||||
|
||||
/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+
|
||||
* Create an internal DDict from dict buffer,
|
||||
* to be used to decompress next frames.
|
||||
* The dictionary remains valid for all future frames, until explicitly invalidated.
|
||||
* Create an internal DDict from dict buffer, to be used to decompress all future frames.
|
||||
* The dictionary remains valid for all future frames, until explicitly invalidated, or
|
||||
* a new dictionary is loaded.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
* Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
|
||||
* meaning "return to no-dictionary mode".
|
||||
@@ -1065,9 +1106,10 @@ ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, s
|
||||
* The memory for the table is allocated on the first call to refDDict, and can be
|
||||
* freed with ZSTD_freeDCtx().
|
||||
*
|
||||
* If called with ZSTD_d_refMultipleDDicts disabled (the default), only one dictionary
|
||||
* will be managed, and referencing a dictionary effectively "discards" any previous one.
|
||||
*
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
* Note 1 : Currently, only one dictionary can be managed.
|
||||
* Referencing a new dictionary effectively "discards" any previous one.
|
||||
* Special: referencing a NULL DDict means "return to no-dictionary mode".
|
||||
* Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.
|
||||
*/
|
||||
@@ -1164,6 +1206,7 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */
|
||||
#define ZSTD_STRATEGY_MIN ZSTD_fast
|
||||
#define ZSTD_STRATEGY_MAX ZSTD_btultra2
|
||||
#define ZSTD_BLOCKSIZE_MAX_MIN (1 << 10) /* The minimum valid max blocksize. Maximum blocksizes smaller than this make compressBound() inaccurate. */
|
||||
|
||||
|
||||
#define ZSTD_OVERLAPLOG_MIN 0
|
||||
@@ -1391,6 +1434,51 @@ ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size
|
||||
* or an error code (if srcSize is too small) */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_decompressionMargin() :
|
||||
* Zstd supports in-place decompression, where the input and output buffers overlap.
|
||||
* In this case, the output buffer must be at least (Margin + Output_Size) bytes large,
|
||||
* and the input buffer must be at the end of the output buffer.
|
||||
*
|
||||
* _______________________ Output Buffer ________________________
|
||||
* | |
|
||||
* | ____ Input Buffer ____|
|
||||
* | | |
|
||||
* v v v
|
||||
* |---------------------------------------|-----------|----------|
|
||||
* ^ ^ ^
|
||||
* |___________________ Output_Size ___________________|_ Margin _|
|
||||
*
|
||||
* NOTE: See also ZSTD_DECOMPRESSION_MARGIN().
|
||||
* NOTE: This applies only to single-pass decompression through ZSTD_decompress() or
|
||||
* ZSTD_decompressDCtx().
|
||||
* NOTE: This function supports multi-frame input.
|
||||
*
|
||||
* @param src The compressed frame(s)
|
||||
* @param srcSize The size of the compressed frame(s)
|
||||
* @returns The decompression margin or an error that can be checked with ZSTD_isError().
|
||||
*/
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSize);
|
||||
|
||||
/*! ZSTD_DECOMPRESS_MARGIN() :
|
||||
* Similar to ZSTD_decompressionMargin(), but instead of computing the margin from
|
||||
* the compressed frame, compute it from the original size and the blockSizeLog.
|
||||
* See ZSTD_decompressionMargin() for details.
|
||||
*
|
||||
* WARNING: This macro does not support multi-frame input, the input must be a single
|
||||
* zstd frame. If you need that support use the function, or implement it yourself.
|
||||
*
|
||||
* @param originalSize The original uncompressed size of the data.
|
||||
* @param blockSize The block size == MIN(windowSize, ZSTD_BLOCKSIZE_MAX).
|
||||
* Unless you explicitly set the windowLog smaller than
|
||||
* ZSTD_BLOCKSIZELOG_MAX you can just use ZSTD_BLOCKSIZE_MAX.
|
||||
*/
|
||||
#define ZSTD_DECOMPRESSION_MARGIN(originalSize, blockSize) ((size_t)( \
|
||||
ZSTD_FRAMEHEADERSIZE_MAX /* Frame header */ + \
|
||||
4 /* checksum */ + \
|
||||
((originalSize) == 0 ? 0 : 3 * (((originalSize) + (blockSize) - 1) / blockSize)) /* 3 bytes per block */ + \
|
||||
(blockSize) /* One block of margin */ \
|
||||
))
|
||||
|
||||
typedef enum {
|
||||
ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
|
||||
ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */
|
||||
@@ -1536,8 +1624,11 @@ ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
|
||||
* and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter().
|
||||
* Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits.
|
||||
*
|
||||
* Note 2 : only single-threaded compression is supported.
|
||||
* Note : only single-threaded compression is supported.
|
||||
* ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
*
|
||||
* Note 2 : ZSTD_estimateCCtxSize* functions are not compatible with the external matchfinder API at this time.
|
||||
* Size estimates assume that no external matchfinder is registered.
|
||||
*/
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
@@ -1556,7 +1647,12 @@ ZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);
|
||||
* or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();
|
||||
* Note : if streaming is init with function ZSTD_init?Stream_usingDict(),
|
||||
* an internal ?Dict will be created, which additional size is not estimated here.
|
||||
* In this case, get total size by adding ZSTD_estimate?DictSize */
|
||||
* In this case, get total size by adding ZSTD_estimate?DictSize
|
||||
* Note 2 : only single-threaded compression is supported.
|
||||
* ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
|
||||
* Note 3 : ZSTD_estimateCStreamSize* functions are not compatible with the external matchfinder API at this time.
|
||||
* Size estimates assume that no external matchfinder is registered.
|
||||
*/
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
|
||||
@@ -1706,6 +1802,13 @@ ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
* This function never fails (wide contract) */
|
||||
ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_CCtx_setCParams() :
|
||||
* Set all parameters provided within @cparams into the working @cctx.
|
||||
* Note : if modifying parameters during compression (MT mode only),
|
||||
* note that changes to the .windowLog parameter will be ignored.
|
||||
* @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams);
|
||||
|
||||
/*! ZSTD_compress_advanced() :
|
||||
* Note : this function is now DEPRECATED.
|
||||
* It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.
|
||||
@@ -1713,10 +1816,10 @@ ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressio
|
||||
ZSTD_DEPRECATED("use ZSTD_compress2")
|
||||
ZSTDLIB_STATIC_API
|
||||
size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
ZSTD_parameters params);
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize,
|
||||
ZSTD_parameters params);
|
||||
|
||||
/*! ZSTD_compress_usingCDict_advanced() :
|
||||
* Note : this function is now DEPRECATED.
|
||||
@@ -2010,6 +2113,55 @@ ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const vo
|
||||
*/
|
||||
#define ZSTD_c_prefetchCDictTables ZSTD_c_experimentalParam16
|
||||
|
||||
/* ZSTD_c_enableMatchFinderFallback
|
||||
* Allowed values are 0 (disable) and 1 (enable). The default setting is 0.
|
||||
*
|
||||
* Controls whether zstd will fall back to an internal matchfinder if an
|
||||
* external matchfinder is registered and returns an error code. This fallback is
|
||||
* block-by-block: the internal matchfinder will only be called for blocks where
|
||||
* the external matchfinder returns an error code. Fallback compression will
|
||||
* follow any other cParam settings, such as compression level, the same as in a
|
||||
* normal (fully-internal) compression operation.
|
||||
*
|
||||
* The user is strongly encouraged to read the full external matchfinder API
|
||||
* documentation (below) before setting this parameter. */
|
||||
#define ZSTD_c_enableMatchFinderFallback ZSTD_c_experimentalParam17
|
||||
|
||||
/* ZSTD_c_maxBlockSize
|
||||
* Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB).
|
||||
* The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default.
|
||||
*
|
||||
* This parameter can be used to set an upper bound on the blocksize
|
||||
* that overrides the default ZSTD_BLOCKSIZE_MAX. It cannot be used to set upper
|
||||
* bounds greater than ZSTD_BLOCKSIZE_MAX or bounds lower than 1KB (will make
|
||||
* compressBound() innacurate). Only currently meant to be used for testing.
|
||||
*
|
||||
*/
|
||||
#define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18
|
||||
|
||||
/* ZSTD_c_searchForExternalRepcodes
|
||||
* This parameter affects how zstd parses external sequences, such as sequences
|
||||
* provided through the compressSequences() API or from an external matchfinder.
|
||||
*
|
||||
* If set to ZSTD_ps_enable, the library will check for repeated offsets in
|
||||
* external sequences, even if those repcodes are not explicitly indicated in
|
||||
* the "rep" field. Note that this is the only way to exploit repcode matches
|
||||
* while using compressSequences() or an external matchfinder, since zstd
|
||||
* currently ignores the "rep" field of external sequences.
|
||||
*
|
||||
* If set to ZSTD_ps_disable, the library will not exploit repeated offsets in
|
||||
* external sequences, regardless of whether the "rep" field has been set. This
|
||||
* reduces sequence compression overhead by about 25% while sacrificing some
|
||||
* compression ratio.
|
||||
*
|
||||
* The default value is ZSTD_ps_auto, for which the library will enable/disable
|
||||
* based on compression level.
|
||||
*
|
||||
* Note: for now, this param only has an effect if ZSTD_c_blockDelimiters is
|
||||
* set to ZSTD_sf_explicitBlockDelimiters. That may change in the future.
|
||||
*/
|
||||
#define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19
|
||||
|
||||
/*! ZSTD_CCtx_getParameter() :
|
||||
* Get the requested compression parameter value, selected by enum ZSTD_cParameter,
|
||||
* and store it into int* value.
|
||||
@@ -2219,6 +2371,17 @@ ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParamete
|
||||
*/
|
||||
#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4
|
||||
|
||||
/* ZSTD_d_disableHuffmanAssembly
|
||||
* Set to 1 to disable the Huffman assembly implementation.
|
||||
* The default value is 0, which allows zstd to use the Huffman assembly
|
||||
* implementation if available.
|
||||
*
|
||||
* This parameter can be used to disable Huffman assembly at runtime.
|
||||
* If you want to disable it at compile time you can define the macro
|
||||
* ZSTD_DISABLE_ASM.
|
||||
*/
|
||||
#define ZSTD_d_disableHuffmanAssembly ZSTD_d_experimentalParam5
|
||||
|
||||
|
||||
/*! ZSTD_DCtx_setFormat() :
|
||||
* This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().
|
||||
@@ -2408,8 +2571,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
|
||||
* ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
|
||||
*
|
||||
* note: no dictionary will be used if dict == NULL or dictSize < 8
|
||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
||||
*/
|
||||
ZSTD_DEPRECATED("use ZSTD_DCtx_reset + ZSTD_DCtx_loadDictionary, see zstd.h for detailed instructions")
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
|
||||
|
||||
/*!
|
||||
@@ -2419,8 +2582,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const vo
|
||||
* ZSTD_DCtx_refDDict(zds, ddict);
|
||||
*
|
||||
* note : ddict is referenced, it must outlive decompression session
|
||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
||||
*/
|
||||
ZSTD_DEPRECATED("use ZSTD_DCtx_reset + ZSTD_DCtx_refDDict, see zstd.h for detailed instructions")
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
|
||||
|
||||
/*!
|
||||
@@ -2429,8 +2592,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const Z
|
||||
* ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
|
||||
*
|
||||
* re-use decompression parameters from previous init; saves dictionary loading
|
||||
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
|
||||
*/
|
||||
ZSTD_DEPRECATED("use ZSTD_DCtx_reset, see zstd.h for detailed instructions")
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
|
||||
|
||||
|
||||
@@ -2476,8 +2639,8 @@ ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLev
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
|
||||
|
||||
ZSTDLIB_STATIC_API
|
||||
ZSTD_DEPRECATED("This function will likely be removed in a future release. It is misleading and has very limited utility.")
|
||||
ZSTDLIB_STATIC_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_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
@@ -2501,8 +2664,8 @@ size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_
|
||||
Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.
|
||||
Data fragment must be large enough to ensure successful decoding.
|
||||
`ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.
|
||||
@result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.
|
||||
>0 : `srcSize` is too small, please provide at least @result bytes on next attempt.
|
||||
result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.
|
||||
>0 : `srcSize` is too small, please provide at least result bytes on next attempt.
|
||||
errorCode, which can be tested using ZSTD_isError().
|
||||
|
||||
It fills a ZSTD_frameHeader structure with important information to correctly decode the frame,
|
||||
@@ -2521,7 +2684,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_
|
||||
|
||||
The most memory efficient way is to use a round buffer of sufficient size.
|
||||
Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(),
|
||||
which can @return an error code if required value is too large for current system (in 32-bits mode).
|
||||
which can return an error code if required value is too large for current system (in 32-bits mode).
|
||||
In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one,
|
||||
up to the moment there is not enough room left in the buffer to guarantee decoding another full block,
|
||||
which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`.
|
||||
@@ -2541,7 +2704,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_
|
||||
ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().
|
||||
ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.
|
||||
|
||||
@result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
|
||||
result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
|
||||
It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item.
|
||||
It can also be an error code, which can be tested with ZSTD_isError().
|
||||
|
||||
@@ -2573,6 +2736,8 @@ typedef struct {
|
||||
unsigned headerSize;
|
||||
unsigned dictID;
|
||||
unsigned checksumFlag;
|
||||
unsigned _reserved1;
|
||||
unsigned _reserved2;
|
||||
} ZSTD_frameHeader;
|
||||
|
||||
/*! ZSTD_getFrameHeader() :
|
||||
@@ -2640,6 +2805,157 @@ ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_
|
||||
ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
|
||||
|
||||
|
||||
/* ********************** EXTERNAL MATCHFINDER API **********************
|
||||
*
|
||||
* *** OVERVIEW ***
|
||||
* This API allows users to replace the zstd internal block-level matchfinder
|
||||
* with an external matchfinder function. Potential applications of the API
|
||||
* include hardware-accelerated matchfinders and matchfinders specialized to
|
||||
* particular types of data.
|
||||
*
|
||||
* See contrib/externalMatchfinder for an example program employing the
|
||||
* external matchfinder API.
|
||||
*
|
||||
* *** USAGE ***
|
||||
* The user is responsible for implementing a function of type
|
||||
* ZSTD_externalMatchFinder_F. For each block, zstd will pass the following
|
||||
* arguments to the user-provided function:
|
||||
*
|
||||
* - externalMatchState: a pointer to a user-managed state for the external
|
||||
* matchfinder.
|
||||
*
|
||||
* - outSeqs, outSeqsCapacity: an output buffer for sequences produced by the
|
||||
* external matchfinder. outSeqsCapacity is guaranteed >=
|
||||
* ZSTD_sequenceBound(srcSize). The memory backing outSeqs is managed by
|
||||
* the CCtx.
|
||||
*
|
||||
* - src, srcSize: an input buffer which the external matchfinder must parse
|
||||
* into sequences. srcSize is guaranteed to be <= ZSTD_BLOCKSIZE_MAX.
|
||||
*
|
||||
* - dict, dictSize: a history buffer, which may be empty, which the external
|
||||
* matchfinder may reference as it produces sequences for the src buffer.
|
||||
* Currently, zstd will always pass dictSize == 0 into external matchfinders,
|
||||
* but this will change in the future.
|
||||
*
|
||||
* - compressionLevel: a signed integer representing the zstd compression level
|
||||
* set by the user for the current operation. The external matchfinder may
|
||||
* choose to use this information to change its compression strategy and
|
||||
* speed/ratio tradeoff. Note: The compression level does not reflect zstd
|
||||
* parameters set through the advanced API.
|
||||
*
|
||||
* - windowSize: a size_t representing the maximum allowed offset for external
|
||||
* sequences. Note that sequence offsets are sometimes allowed to exceed the
|
||||
* windowSize if a dictionary is present, see doc/zstd_compression_format.md
|
||||
* for details.
|
||||
*
|
||||
* The user-provided function shall return a size_t representing the number of
|
||||
* sequences written to outSeqs. This return value will be treated as an error
|
||||
* code if it is greater than outSeqsCapacity. The return value must be non-zero
|
||||
* if srcSize is non-zero. The ZSTD_EXTERNAL_MATCHFINDER_ERROR macro is provided
|
||||
* for convenience, but any value greater than outSeqsCapacity will be treated as
|
||||
* an error code.
|
||||
*
|
||||
* If the user-provided function does not return an error code, the sequences
|
||||
* written to outSeqs must be a valid parse of the src buffer. Data corruption may
|
||||
* occur if the parse is not valid. A parse is defined to be valid if the
|
||||
* following conditions hold:
|
||||
* - The sum of matchLengths and literalLengths is equal to srcSize.
|
||||
* - All sequences in the parse have matchLength != 0, except for the final
|
||||
* sequence. matchLength is not constrained for the final sequence.
|
||||
* - All offsets respect the windowSize parameter as specified in
|
||||
* doc/zstd_compression_format.md.
|
||||
*
|
||||
* zstd will only validate these conditions (and fail compression if they do not
|
||||
* hold) if the ZSTD_c_validateSequences cParam is enabled. Note that sequence
|
||||
* validation has a performance cost.
|
||||
*
|
||||
* If the user-provided function returns an error, zstd will either fall back
|
||||
* to an internal matchfinder or fail the compression operation. The user can
|
||||
* choose between the two behaviors by setting the
|
||||
* ZSTD_c_enableMatchFinderFallback cParam. Fallback compression will follow any
|
||||
* other cParam settings, such as compression level, the same as in a normal
|
||||
* compression operation.
|
||||
*
|
||||
* The user shall instruct zstd to use a particular ZSTD_externalMatchFinder_F
|
||||
* function by calling ZSTD_registerExternalMatchFinder(cctx, externalMatchState,
|
||||
* externalMatchFinder). This setting will persist until the next parameter reset
|
||||
* of the CCtx.
|
||||
*
|
||||
* The externalMatchState must be initialized by the user before calling
|
||||
* ZSTD_registerExternalMatchFinder. The user is responsible for destroying the
|
||||
* externalMatchState.
|
||||
*
|
||||
* *** LIMITATIONS ***
|
||||
* External matchfinders are compatible with all zstd compression APIs which respect
|
||||
* advanced parameters. However, there are three limitations:
|
||||
*
|
||||
* First, the ZSTD_c_enableLongDistanceMatching cParam is not supported.
|
||||
* COMPRESSION WILL FAIL if it is enabled and the user tries to compress with an
|
||||
* external matchfinder.
|
||||
* - Note that ZSTD_c_enableLongDistanceMatching is auto-enabled by default in
|
||||
* some cases (see its documentation for details). Users must explicitly set
|
||||
* ZSTD_c_enableLongDistanceMatching to ZSTD_ps_disable in such cases if an
|
||||
* external matchfinder is registered.
|
||||
* - As of this writing, ZSTD_c_enableLongDistanceMatching is disabled by default
|
||||
* whenever ZSTD_c_windowLog < 128MB, but that's subject to change. Users should
|
||||
* check the docs on ZSTD_c_enableLongDistanceMatching whenever the external
|
||||
* matchfinder API is used in conjunction with advanced settings (like windowLog).
|
||||
*
|
||||
* Second, history buffers are not supported. Concretely, zstd will always pass
|
||||
* dictSize == 0 to the external matchfinder (for now). This has two implications:
|
||||
* - Dictionaries are not supported. Compression will *not* fail if the user
|
||||
* references a dictionary, but the dictionary won't have any effect.
|
||||
* - Stream history is not supported. All compression APIs, including streaming
|
||||
* APIs, work with the external matchfinder, but the external matchfinder won't
|
||||
* receive any history from the previous block. Each block is an independent chunk.
|
||||
*
|
||||
* Third, multi-threading within a single compression is not supported. In other words,
|
||||
* COMPRESSION WILL FAIL if ZSTD_c_nbWorkers > 0 and an external matchfinder is registered.
|
||||
* Multi-threading across compressions is fine: simply create one CCtx per thread.
|
||||
*
|
||||
* Long-term, we plan to overcome all three limitations. There is no technical blocker to
|
||||
* overcoming them. It is purely a question of engineering effort.
|
||||
*/
|
||||
|
||||
#define ZSTD_EXTERNAL_MATCHFINDER_ERROR ((size_t)(-1))
|
||||
|
||||
typedef size_t ZSTD_externalMatchFinder_F (
|
||||
void* externalMatchState,
|
||||
ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict, size_t dictSize,
|
||||
int compressionLevel,
|
||||
size_t windowSize
|
||||
);
|
||||
|
||||
/*! ZSTD_registerExternalMatchFinder() :
|
||||
* Instruct zstd to use an external matchfinder function.
|
||||
*
|
||||
* The externalMatchState must be initialized by the caller, and the caller is
|
||||
* responsible for managing its lifetime. This parameter is sticky across
|
||||
* compressions. It will remain set until the user explicitly resets compression
|
||||
* parameters.
|
||||
*
|
||||
* External matchfinder registration is considered to be an "advanced parameter",
|
||||
* part of the "advanced API". This means it will only have an effect on
|
||||
* compression APIs which respect advanced parameters, such as compress2() and
|
||||
* compressStream(). Older compression APIs such as compressCCtx(), which predate
|
||||
* the introduction of "advanced parameters", will ignore any external matchfinder
|
||||
* setting.
|
||||
*
|
||||
* The external matchfinder can be "cleared" by registering a NULL external
|
||||
* matchfinder function pointer. This removes all limitations described above in
|
||||
* the "LIMITATIONS" section of the API docs.
|
||||
*
|
||||
* The user is strongly encouraged to read the full API documentation (above)
|
||||
* before calling this function. */
|
||||
ZSTDLIB_STATIC_API void
|
||||
ZSTD_registerExternalMatchFinder(
|
||||
ZSTD_CCtx* cctx,
|
||||
void* externalMatchState,
|
||||
ZSTD_externalMatchFinder_F* externalMatchFinder
|
||||
);
|
||||
|
||||
#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
|
||||
|
||||
#if defined (__cplusplus)
|
||||
|
||||
+26
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) Yann Collet, Facebook, Inc.
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under both the BSD-style license (found in the
|
||||
@@ -20,19 +20,31 @@ extern "C" {
|
||||
|
||||
|
||||
/* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */
|
||||
#ifndef ZSTDERRORLIB_VISIBILITY
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define ZSTDERRORLIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||
#ifndef ZSTDERRORLIB_VISIBLE
|
||||
/* Backwards compatibility with old macro name */
|
||||
# ifdef ZSTDERRORLIB_VISIBILITY
|
||||
# define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY
|
||||
# elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define ZSTDERRORLIB_VISIBILITY
|
||||
# define ZSTDERRORLIB_VISIBLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZSTDERRORLIB_HIDDEN
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
|
||||
# define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility ("hidden")))
|
||||
# else
|
||||
# define ZSTDERRORLIB_HIDDEN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
|
||||
# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBILITY
|
||||
# define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE
|
||||
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
|
||||
# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
# define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY
|
||||
# define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE
|
||||
#endif
|
||||
|
||||
/*-*********************************************
|
||||
@@ -58,10 +70,12 @@ typedef enum {
|
||||
ZSTD_error_frameParameter_windowTooLarge = 16,
|
||||
ZSTD_error_corruption_detected = 20,
|
||||
ZSTD_error_checksum_wrong = 22,
|
||||
ZSTD_error_literals_headerWrong = 24,
|
||||
ZSTD_error_dictionary_corrupted = 30,
|
||||
ZSTD_error_dictionary_wrong = 32,
|
||||
ZSTD_error_dictionaryCreation_failed = 34,
|
||||
ZSTD_error_parameter_unsupported = 40,
|
||||
ZSTD_error_parameter_combination_unsupported = 41,
|
||||
ZSTD_error_parameter_outOfBound = 42,
|
||||
ZSTD_error_tableLog_tooLarge = 44,
|
||||
ZSTD_error_maxSymbolValue_tooLarge = 46,
|
||||
@@ -74,11 +88,15 @@ typedef enum {
|
||||
ZSTD_error_dstSize_tooSmall = 70,
|
||||
ZSTD_error_srcSize_wrong = 72,
|
||||
ZSTD_error_dstBuffer_null = 74,
|
||||
ZSTD_error_noForwardProgress_destFull = 80,
|
||||
ZSTD_error_noForwardProgress_inputEmpty = 82,
|
||||
/* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
|
||||
ZSTD_error_frameIndex_tooLarge = 100,
|
||||
ZSTD_error_seekableIO = 102,
|
||||
ZSTD_error_dstBuffer_wrong = 104,
|
||||
ZSTD_error_srcBuffer_wrong = 105,
|
||||
ZSTD_error_externalMatchFinder_failed = 106,
|
||||
ZSTD_error_externalSequences_invalid = 107,
|
||||
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
|
||||
} ZSTD_ErrorCode;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user