@@ -58,7 +58,9 @@ extern "C" {
|
||||
#if defined(BIT_DEBUG) && (BIT_DEBUG>=1)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# define assert(condition) ((void)0)
|
||||
# ifndef assert
|
||||
# define assert(condition) ((void)0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -73,6 +75,7 @@ extern "C" {
|
||||
#define STREAM_ACCUMULATOR_MIN_64 57
|
||||
#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
|
||||
|
||||
|
||||
/*-******************************************
|
||||
* bitStream encoding API (write forward)
|
||||
********************************************/
|
||||
@@ -307,19 +310,19 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
|
||||
|
||||
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
|
||||
/* fall-through */
|
||||
|
||||
|
||||
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
|
||||
/* fall-through */
|
||||
|
||||
|
||||
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
|
||||
/* fall-through */
|
||||
|
||||
|
||||
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
|
||||
/* fall-through */
|
||||
|
||||
|
||||
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
|
||||
/* fall-through */
|
||||
|
||||
|
||||
default: break;
|
||||
}
|
||||
{ BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
|
||||
|
||||
@@ -24,7 +24,8 @@ const char* ERR_getErrorString(ERR_enum code)
|
||||
case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
|
||||
case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
|
||||
case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding";
|
||||
case PREFIX(compressionParameter_unsupported): return "Compression parameter is out of bound";
|
||||
case PREFIX(compressionParameter_unsupported): return "Compression parameter is not supported";
|
||||
case PREFIX(compressionParameter_outOfBound): return "Compression parameter is out of bound";
|
||||
case PREFIX(init_missing): return "Context should be init first";
|
||||
case PREFIX(memory_allocation): return "Allocation error : not enough memory";
|
||||
case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
|
||||
|
||||
@@ -352,20 +352,6 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)
|
||||
}
|
||||
|
||||
|
||||
/* function safe only for comparisons */
|
||||
MEM_STATIC U32 MEM_readMINMATCH(const void* memPtr, U32 length)
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
default :
|
||||
case 4 : return MEM_read32(memPtr);
|
||||
case 3 : if (MEM_isLittleEndian())
|
||||
return MEM_read32(memPtr)<<8;
|
||||
else
|
||||
return MEM_read32(memPtr)>>8;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -146,6 +146,13 @@ void POOL_free(POOL_ctx *ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
size_t POOL_sizeof(POOL_ctx *ctx) {
|
||||
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
||||
return sizeof(*ctx)
|
||||
+ ctx->queueSize * sizeof(POOL_job)
|
||||
+ ctx->numThreads * sizeof(pthread_t);
|
||||
}
|
||||
|
||||
void POOL_add(void *ctxVoid, POOL_function function, void *opaque) {
|
||||
POOL_ctx *ctx = (POOL_ctx *)ctxVoid;
|
||||
if (!ctx) { return; }
|
||||
@@ -191,4 +198,9 @@ void POOL_add(void *ctx, POOL_function function, void *opaque) {
|
||||
function(opaque);
|
||||
}
|
||||
|
||||
size_t POOL_sizeof(POOL_ctx *ctx) {
|
||||
if (ctx==NULL) return 0; /* supports sizeof NULL */
|
||||
return sizeof(*ctx);
|
||||
}
|
||||
|
||||
#endif /* ZSTD_MULTITHREAD */
|
||||
|
||||
@@ -32,6 +32,11 @@ POOL_ctx *POOL_create(size_t numThreads, size_t queueSize);
|
||||
*/
|
||||
void POOL_free(POOL_ctx *ctx);
|
||||
|
||||
/*! POOL_sizeof() :
|
||||
return memory usage of pool returned by POOL_create().
|
||||
*/
|
||||
size_t POOL_sizeof(POOL_ctx *ctx);
|
||||
|
||||
/*! POOL_function :
|
||||
The function type that can be added to a thread pool.
|
||||
*/
|
||||
|
||||
+24
-19
@@ -12,7 +12,8 @@
|
||||
/*-*************************************
|
||||
* Dependencies
|
||||
***************************************/
|
||||
#include <stdlib.h> /* malloc */
|
||||
#include <stdlib.h> /* malloc, calloc, free */
|
||||
#include <string.h> /* memset */
|
||||
#include "error_private.h"
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#include "zstd.h"
|
||||
@@ -21,7 +22,7 @@
|
||||
/*-****************************************
|
||||
* Version
|
||||
******************************************/
|
||||
unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; }
|
||||
unsigned ZSTD_versionNumber(void) { return ZSTD_VERSION_NUMBER; }
|
||||
|
||||
const char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; }
|
||||
|
||||
@@ -49,27 +50,31 @@ const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString
|
||||
/*=**************************************************************
|
||||
* Custom allocator
|
||||
****************************************************************/
|
||||
/* default uses stdlib */
|
||||
void* ZSTD_defaultAllocFunction(void* opaque, size_t size)
|
||||
{
|
||||
void* address = malloc(size);
|
||||
(void)opaque;
|
||||
return address;
|
||||
}
|
||||
|
||||
void ZSTD_defaultFreeFunction(void* opaque, void* address)
|
||||
{
|
||||
(void)opaque;
|
||||
free(address);
|
||||
}
|
||||
|
||||
void* ZSTD_malloc(size_t size, ZSTD_customMem customMem)
|
||||
{
|
||||
return customMem.customAlloc(customMem.opaque, size);
|
||||
if (customMem.customAlloc)
|
||||
return customMem.customAlloc(customMem.opaque, size);
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void* ZSTD_calloc(size_t size, ZSTD_customMem customMem)
|
||||
{
|
||||
if (customMem.customAlloc) {
|
||||
/* calloc implemented as malloc+memset;
|
||||
* not as efficient as calloc, but next best guess for custom malloc */
|
||||
void* const ptr = customMem.customAlloc(customMem.opaque, size);
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
return calloc(1, size);
|
||||
}
|
||||
|
||||
void ZSTD_free(void* ptr, ZSTD_customMem customMem)
|
||||
{
|
||||
if (ptr!=NULL)
|
||||
customMem.customFree(customMem.opaque, ptr);
|
||||
if (ptr!=NULL) {
|
||||
if (customMem.customFree)
|
||||
customMem.customFree(customMem.opaque, ptr);
|
||||
else
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,11 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*-****************************************
|
||||
* error codes list
|
||||
******************************************/
|
||||
* error codes list
|
||||
* note : this API is still considered unstable
|
||||
* it should not be used with a dynamic library
|
||||
* only static linking is allowed
|
||||
******************************************/
|
||||
typedef enum {
|
||||
ZSTD_error_no_error,
|
||||
ZSTD_error_GENERIC,
|
||||
@@ -47,6 +50,7 @@ typedef enum {
|
||||
ZSTD_error_frameParameter_unsupportedBy32bits,
|
||||
ZSTD_error_frameParameter_windowTooLarge,
|
||||
ZSTD_error_compressionParameter_unsupported,
|
||||
ZSTD_error_compressionParameter_outOfBound,
|
||||
ZSTD_error_init_missing,
|
||||
ZSTD_error_memory_allocation,
|
||||
ZSTD_error_stage_wrong,
|
||||
@@ -67,7 +71,7 @@ typedef enum {
|
||||
|
||||
/*! ZSTD_getErrorCode() :
|
||||
convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
|
||||
which can be used to compare directly with enum list published into "error_public.h" */
|
||||
which can be used to compare with enum list published above */
|
||||
ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
|
||||
ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# include <intrin.h> /* For Visual 2005 */
|
||||
# pragma warning(disable : 4100) /* disable: C4100: unreferenced formal parameter */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||
# pragma warning(disable : 4324) /* disable: C4324: padded structure */
|
||||
#else
|
||||
# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
@@ -50,9 +51,36 @@
|
||||
#define ZSTD_STATIC_LINKING_ONLY
|
||||
#include "zstd.h"
|
||||
#ifndef XXH_STATIC_LINKING_ONLY
|
||||
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||
# define XXH_STATIC_LINKING_ONLY /* XXH64_state_t */
|
||||
#endif
|
||||
#include "xxhash.h" /* XXH_reset, update, digest */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Debug
|
||||
***************************************/
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# ifndef assert
|
||||
# define assert(condition) ((void)0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define ZSTD_STATIC_ASSERT(c) { enum { ZSTD_static_assert = 1/(int)(!!(c)) }; }
|
||||
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
|
||||
# include <stdio.h>
|
||||
static unsigned g_debugLevel = ZSTD_DEBUG;
|
||||
# define DEBUGLOG(l, ...) { \
|
||||
if (l<=g_debugLevel) { \
|
||||
fprintf(stderr, __FILE__ ": "); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, " \n"); \
|
||||
} }
|
||||
#else
|
||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||
#endif
|
||||
#include "xxhash.h" /* XXH_reset, update, digest */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -235,15 +263,10 @@ typedef struct {
|
||||
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);
|
||||
void ZSTD_seqToCodes(const seqStore_t* seqStorePtr);
|
||||
int ZSTD_isSkipFrame(ZSTD_DCtx* dctx);
|
||||
|
||||
/* custom memory allocation functions */
|
||||
void* ZSTD_defaultAllocFunction(void* opaque, size_t size);
|
||||
void ZSTD_defaultFreeFunction(void* opaque, void* address);
|
||||
#ifndef ZSTD_DLL_IMPORT
|
||||
static const ZSTD_customMem defaultCustomMem = { ZSTD_defaultAllocFunction, ZSTD_defaultFreeFunction, NULL };
|
||||
#endif
|
||||
void* ZSTD_malloc(size_t size, ZSTD_customMem customMem);
|
||||
void* ZSTD_calloc(size_t size, ZSTD_customMem customMem);
|
||||
void ZSTD_free(void* ptr, ZSTD_customMem customMem);
|
||||
|
||||
|
||||
@@ -281,4 +304,34 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val)
|
||||
void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);
|
||||
|
||||
|
||||
typedef enum { ZSTDb_not_buffered, ZSTDb_buffered } ZSTD_buffered_policy_e;
|
||||
#if 0
|
||||
/*! ZSTD_compressBegin_internal() :
|
||||
* innermost initialization function. Private use only.
|
||||
* expects params to be valid.
|
||||
* must receive dict, or cdict, or none, but not both.
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
||||
const void* dict, size_t dictSize,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize,
|
||||
ZSTD_buffered_policy_e zbuff);
|
||||
#endif
|
||||
|
||||
/*! ZSTD_initCStream_internal() :
|
||||
* Private use only. Init streaming operation.
|
||||
* expects params to be valid.
|
||||
* must receive dict, or cdict, or none, but not both.
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
||||
const void* dict, size_t dictSize,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize);
|
||||
|
||||
|
||||
/*! ZSTD_getParamsFromCDict() :
|
||||
* as the name implies */
|
||||
ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict);
|
||||
|
||||
|
||||
#endif /* ZSTD_CCOMMON_H_MODULE */
|
||||
|
||||
+911
-427
@@ -8,6 +8,14 @@
|
||||
*/
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Tuning parameters
|
||||
***************************************/
|
||||
#ifndef ZSTD_CLEVEL_DEFAULT
|
||||
# define ZSTD_CLEVEL_DEFAULT 3
|
||||
#endif
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Dependencies
|
||||
***************************************/
|
||||
@@ -18,26 +26,7 @@
|
||||
#define HUF_STATIC_LINKING_ONLY
|
||||
#include "huf.h"
|
||||
#include "zstd_internal.h" /* includes zstd.h */
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Debug
|
||||
***************************************/
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=1)
|
||||
# include <assert.h>
|
||||
#else
|
||||
# define assert(condition) ((void)0)
|
||||
#endif
|
||||
|
||||
#define ZSTD_STATIC_ASSERT(c) { enum { ZSTD_static_assert = 1/(int)(!!(c)) }; }
|
||||
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
|
||||
# include <stdio.h>
|
||||
static unsigned g_debugLevel = ZSTD_DEBUG;
|
||||
# define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
|
||||
#else
|
||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||
#endif
|
||||
#include "zstdmt_compress.h"
|
||||
|
||||
|
||||
/*-*************************************
|
||||
@@ -79,7 +68,14 @@ static void ZSTD_resetSeqStore(seqStore_t* ssPtr)
|
||||
/*-*************************************
|
||||
* Context memory management
|
||||
***************************************/
|
||||
typedef enum { zcss_init, zcss_load, zcss_flush, zcss_final } ZSTD_cStreamStage;
|
||||
typedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;
|
||||
|
||||
struct ZSTD_CDict_s {
|
||||
void* dictBuffer;
|
||||
const void* dictContent;
|
||||
size_t dictContentSize;
|
||||
ZSTD_CCtx* refContext;
|
||||
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
|
||||
|
||||
struct ZSTD_CCtx_s {
|
||||
const BYTE* nextSrc; /* next block here to continue on current prefix */
|
||||
@@ -92,19 +88,22 @@ struct ZSTD_CCtx_s {
|
||||
U32 hashLog3; /* dispatch table : larger == faster, more memory */
|
||||
U32 loadedDictEnd; /* index of end of dictionary */
|
||||
U32 forceWindow; /* force back-references to respect limit of 1<<wLog, even for dictionary */
|
||||
U32 forceRawDict; /* Force loading dictionary in "content-only" mode (no header analysis) */
|
||||
ZSTD_dictMode_e dictMode; /* select restricting dictionary to "rawContent" or "fullDict" only */
|
||||
ZSTD_compressionStage_e stage;
|
||||
U32 rep[ZSTD_REP_NUM];
|
||||
U32 repToConfirm[ZSTD_REP_NUM];
|
||||
U32 dictID;
|
||||
ZSTD_parameters params;
|
||||
int compressionLevel;
|
||||
ZSTD_parameters requestedParams;
|
||||
ZSTD_parameters appliedParams;
|
||||
void* workSpace;
|
||||
size_t workSpaceSize;
|
||||
size_t blockSize;
|
||||
U64 frameContentSize;
|
||||
U64 pledgedSrcSizePlusOne; /* this way, 0 (default) == unknown */
|
||||
U64 consumedSrcSize;
|
||||
XXH64_state_t xxhState;
|
||||
ZSTD_customMem customMem;
|
||||
size_t staticSize;
|
||||
|
||||
seqStore_t seqStore; /* sequences storage ptrs */
|
||||
U32* hashTable;
|
||||
@@ -132,39 +131,71 @@ struct ZSTD_CCtx_s {
|
||||
size_t outBuffFlushedSize;
|
||||
ZSTD_cStreamStage streamStage;
|
||||
U32 frameEnded;
|
||||
U64 pledgedSrcSize;
|
||||
|
||||
/* Multi-threading */
|
||||
U32 nbThreads;
|
||||
ZSTDMT_CCtx* mtctx;
|
||||
};
|
||||
|
||||
|
||||
ZSTD_CCtx* ZSTD_createCCtx(void)
|
||||
{
|
||||
return ZSTD_createCCtx_advanced(defaultCustomMem);
|
||||
return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)
|
||||
{
|
||||
ZSTD_CCtx* cctx;
|
||||
|
||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
||||
|
||||
cctx = (ZSTD_CCtx*) ZSTD_malloc(sizeof(ZSTD_CCtx), customMem);
|
||||
cctx = (ZSTD_CCtx*) ZSTD_calloc(sizeof(ZSTD_CCtx), customMem);
|
||||
if (!cctx) return NULL;
|
||||
memset(cctx, 0, sizeof(ZSTD_CCtx));
|
||||
cctx->customMem = customMem;
|
||||
cctx->compressionLevel = ZSTD_CLEVEL_DEFAULT;
|
||||
ZSTD_STATIC_ASSERT(zcss_init==0);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));
|
||||
return cctx;
|
||||
}
|
||||
|
||||
ZSTD_CCtx* ZSTD_initStaticCCtx(void *workspace, size_t workspaceSize)
|
||||
{
|
||||
ZSTD_CCtx* cctx = (ZSTD_CCtx*) workspace;
|
||||
if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */
|
||||
if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */
|
||||
memset(workspace, 0, workspaceSize); /* may be a bit generous, could memset be smaller ? */
|
||||
cctx->staticSize = workspaceSize;
|
||||
cctx->workSpace = (void*)(cctx+1);
|
||||
cctx->workSpaceSize = workspaceSize - sizeof(ZSTD_CCtx);
|
||||
|
||||
/* entropy space (never moves) */
|
||||
/* note : this code should be shared with resetCCtx, rather than copy/pasted */
|
||||
{ void* ptr = cctx->workSpace;
|
||||
cctx->hufCTable = (HUF_CElt*)ptr;
|
||||
ptr = (char*)cctx->hufCTable + hufCTable_size;
|
||||
cctx->offcodeCTable = (FSE_CTable*) ptr;
|
||||
ptr = (char*)ptr + offcodeCTable_size;
|
||||
cctx->matchlengthCTable = (FSE_CTable*) ptr;
|
||||
ptr = (char*)ptr + matchlengthCTable_size;
|
||||
cctx->litlengthCTable = (FSE_CTable*) ptr;
|
||||
ptr = (char*)ptr + litlengthCTable_size;
|
||||
assert(((size_t)ptr & 3) == 0); /* ensure correct alignment */
|
||||
cctx->entropyScratchSpace = (unsigned*) ptr;
|
||||
}
|
||||
|
||||
return cctx;
|
||||
}
|
||||
|
||||
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
||||
{
|
||||
if (cctx==NULL) return 0; /* support free on NULL */
|
||||
if (cctx->staticSize) return ERROR(memory_allocation); /* not compatible with static CCtx */
|
||||
ZSTD_free(cctx->workSpace, cctx->customMem);
|
||||
cctx->workSpace = NULL;
|
||||
ZSTD_freeCDict(cctx->cdictLocal);
|
||||
cctx->cdictLocal = NULL;
|
||||
ZSTD_free(cctx->inBuff, cctx->customMem);
|
||||
cctx->inBuff = NULL;
|
||||
ZSTD_free(cctx->outBuff, cctx->customMem);
|
||||
cctx->outBuff = NULL;
|
||||
ZSTDMT_freeCCtx(cctx->mtctx);
|
||||
cctx->mtctx = NULL;
|
||||
ZSTD_free(cctx, cctx->customMem);
|
||||
return 0; /* reserved as a potential error code in the future */
|
||||
}
|
||||
@@ -172,38 +203,263 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
|
||||
size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)
|
||||
{
|
||||
if (cctx==NULL) return 0; /* support sizeof on NULL */
|
||||
DEBUGLOG(5, "sizeof(*cctx) : %u", (U32)sizeof(*cctx));
|
||||
DEBUGLOG(5, "workSpaceSize : %u", (U32)cctx->workSpaceSize);
|
||||
DEBUGLOG(5, "streaming buffers : %u", (U32)(cctx->outBuffSize + cctx->inBuffSize));
|
||||
DEBUGLOG(5, "inner MTCTX : %u", (U32)ZSTDMT_sizeof_CCtx(cctx->mtctx));
|
||||
return sizeof(*cctx) + cctx->workSpaceSize
|
||||
+ ZSTD_sizeof_CDict(cctx->cdictLocal)
|
||||
+ cctx->outBuffSize + cctx->inBuffSize;
|
||||
+ cctx->outBuffSize + cctx->inBuffSize
|
||||
+ ZSTDMT_sizeof_CCtx(cctx->mtctx);
|
||||
}
|
||||
|
||||
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
|
||||
{
|
||||
return ZSTD_sizeof_CCtx(zcs); /* same object */
|
||||
}
|
||||
|
||||
/* private API call, for dictBuilder only */
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }
|
||||
|
||||
static ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx* cctx) { return cctx->appliedParams; }
|
||||
|
||||
/* older variant; will be deprecated */
|
||||
size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case ZSTD_p_forceWindow : cctx->forceWindow = value>0; cctx->loadedDictEnd = 0; return 0;
|
||||
case ZSTD_p_forceRawDict : cctx->forceRawDict = value>0; return 0;
|
||||
ZSTD_STATIC_ASSERT(ZSTD_dm_auto==0);
|
||||
ZSTD_STATIC_ASSERT(ZSTD_dm_rawContent==1);
|
||||
case ZSTD_p_forceRawDict : cctx->dictMode = (ZSTD_dictMode_e)(value>0); return 0;
|
||||
default: return ERROR(parameter_unknown);
|
||||
}
|
||||
}
|
||||
|
||||
const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) /* hidden interface */
|
||||
|
||||
#define ZSTD_CLEVEL_CUSTOM 999
|
||||
static void ZSTD_cLevelToCParams(ZSTD_CCtx* cctx)
|
||||
{
|
||||
return &(ctx->seqStore);
|
||||
if (cctx->compressionLevel==ZSTD_CLEVEL_CUSTOM) return;
|
||||
cctx->requestedParams.cParams = ZSTD_getCParams(cctx->compressionLevel,
|
||||
cctx->pledgedSrcSizePlusOne-1, 0);
|
||||
cctx->compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
||||
}
|
||||
|
||||
static ZSTD_parameters ZSTD_getParamsFromCCtx(const ZSTD_CCtx* cctx)
|
||||
#define CLAMPCHECK(val,min,max) { \
|
||||
if (((val)<(min)) | ((val)>(max))) { \
|
||||
return ERROR(compressionParameter_outOfBound); \
|
||||
} }
|
||||
|
||||
size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value)
|
||||
{
|
||||
return cctx->params;
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case ZSTD_p_compressionLevel :
|
||||
if ((int)value > ZSTD_maxCLevel()) value = ZSTD_maxCLevel(); /* cap max compression level */
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
cctx->compressionLevel = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_windowLog :
|
||||
DEBUGLOG(5, "setting ZSTD_p_windowLog = %u (cdict:%u)",
|
||||
value, (cctx->cdict!=NULL));
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
CLAMPCHECK(value, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
|
||||
ZSTD_cLevelToCParams(cctx);
|
||||
cctx->requestedParams.cParams.windowLog = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_hashLog :
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
CLAMPCHECK(value, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
|
||||
ZSTD_cLevelToCParams(cctx);
|
||||
cctx->requestedParams.cParams.hashLog = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_chainLog :
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
CLAMPCHECK(value, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
|
||||
ZSTD_cLevelToCParams(cctx);
|
||||
cctx->requestedParams.cParams.chainLog = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_searchLog :
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
CLAMPCHECK(value, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
|
||||
ZSTD_cLevelToCParams(cctx);
|
||||
cctx->requestedParams.cParams.searchLog = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_minMatch :
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
CLAMPCHECK(value, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
|
||||
ZSTD_cLevelToCParams(cctx);
|
||||
cctx->requestedParams.cParams.searchLength = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_targetLength :
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
CLAMPCHECK(value, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
|
||||
ZSTD_cLevelToCParams(cctx);
|
||||
cctx->requestedParams.cParams.targetLength = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_compressionStrategy :
|
||||
if (value == 0) return 0; /* special value : 0 means "don't change anything" */
|
||||
if (cctx->cdict) return ERROR(stage_wrong);
|
||||
CLAMPCHECK(value, (unsigned)ZSTD_fast, (unsigned)ZSTD_btultra);
|
||||
ZSTD_cLevelToCParams(cctx);
|
||||
cctx->requestedParams.cParams.strategy = (ZSTD_strategy)value;
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
case ZSTD_p_windowSize : /* to be done later */
|
||||
return ERROR(compressionParameter_unsupported);
|
||||
#endif
|
||||
|
||||
case ZSTD_p_contentSizeFlag :
|
||||
DEBUGLOG(5, "set content size flag = %u", (value>0));
|
||||
/* Content size written in frame header _when known_ (default:1) */
|
||||
cctx->requestedParams.fParams.contentSizeFlag = value>0;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_checksumFlag :
|
||||
/* A 32-bits content checksum will be calculated and written at end of frame (default:0) */
|
||||
cctx->requestedParams.fParams.checksumFlag = value>0;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */
|
||||
DEBUGLOG(5, "set dictIDFlag = %u", (value>0));
|
||||
cctx->requestedParams.fParams.noDictIDFlag = (value==0);
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_refDictContent : /* to be done later */
|
||||
return ERROR(compressionParameter_unsupported);
|
||||
|
||||
case ZSTD_p_dictMode :
|
||||
/* restrict dictionary mode, to "rawContent" or "fullDict" only */
|
||||
ZSTD_STATIC_ASSERT((U32)ZSTD_dm_fullDict > (U32)ZSTD_dm_rawContent);
|
||||
if (value > (unsigned)ZSTD_dm_fullDict)
|
||||
return ERROR(compressionParameter_outOfBound);
|
||||
cctx->dictMode = (ZSTD_dictMode_e)value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_forceMaxWindow : /* Force back-references to remain < windowSize,
|
||||
* even when referencing into Dictionary content
|
||||
* default : 0 when using a CDict, 1 when using a Prefix */
|
||||
cctx->forceWindow = value>0;
|
||||
cctx->loadedDictEnd = 0;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_nbThreads:
|
||||
if (value==0) return 0;
|
||||
DEBUGLOG(5, " setting nbThreads : %u", value);
|
||||
#ifndef ZSTD_MULTITHREAD
|
||||
if (value > 1) return ERROR(compressionParameter_unsupported);
|
||||
#endif
|
||||
if ((value>1) && (cctx->nbThreads != value)) {
|
||||
if (cctx->staticSize) /* MT not compatible with static alloc */
|
||||
return ERROR(compressionParameter_unsupported);
|
||||
ZSTDMT_freeCCtx(cctx->mtctx);
|
||||
cctx->nbThreads = 1;
|
||||
cctx->mtctx = ZSTDMT_createCCtx(value);
|
||||
if (cctx->mtctx == NULL) return ERROR(memory_allocation);
|
||||
}
|
||||
cctx->nbThreads = value;
|
||||
return 0;
|
||||
|
||||
case ZSTD_p_jobSize:
|
||||
if (cctx->nbThreads <= 1) return ERROR(compressionParameter_unsupported);
|
||||
assert(cctx->mtctx != NULL);
|
||||
return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_sectionSize, value);
|
||||
|
||||
case ZSTD_p_overlapSizeLog:
|
||||
DEBUGLOG(5, " setting overlap with nbThreads == %u", cctx->nbThreads);
|
||||
if (cctx->nbThreads <= 1) return ERROR(compressionParameter_unsupported);
|
||||
assert(cctx->mtctx != NULL);
|
||||
return ZSTDMT_setMTCtxParameter(cctx->mtctx, ZSTDMT_p_overlapSectionLog, value);
|
||||
|
||||
default: return ERROR(parameter_unknown);
|
||||
}
|
||||
}
|
||||
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(5, " setting pledgedSrcSize to %u", (U32)pledgedSrcSize);
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** ZSTD_checkParams() :
|
||||
ensure param values remain within authorized range.
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
||||
{
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
if (cctx->staticSize) return ERROR(memory_allocation); /* no malloc for static CCtx */
|
||||
DEBUGLOG(5, "load dictionary of size %u", (U32)dictSize);
|
||||
ZSTD_freeCDict(cctx->cdictLocal); /* in case one already exists */
|
||||
if (dict==NULL || dictSize==0) { /* no dictionary mode */
|
||||
cctx->cdictLocal = NULL;
|
||||
cctx->cdict = NULL;
|
||||
} else {
|
||||
ZSTD_compressionParameters const cParams =
|
||||
cctx->compressionLevel == ZSTD_CLEVEL_CUSTOM ?
|
||||
cctx->requestedParams.cParams :
|
||||
ZSTD_getCParams(cctx->compressionLevel, 0, dictSize);
|
||||
cctx->cdictLocal = ZSTD_createCDict_advanced(
|
||||
dict, dictSize,
|
||||
0 /* byReference */, cctx->dictMode,
|
||||
cParams, cctx->customMem);
|
||||
cctx->cdict = cctx->cdictLocal;
|
||||
if (cctx->cdictLocal == NULL)
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Not ready yet ! */
|
||||
size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)
|
||||
{
|
||||
(void)cctx; (void)prefix; (void)prefixSize; /* to be done later */
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
return ERROR(compressionParameter_unsupported);
|
||||
}
|
||||
|
||||
size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
||||
{
|
||||
if (cctx->streamStage != zcss_init) return ERROR(stage_wrong);
|
||||
cctx->cdict = cdict;
|
||||
return ERROR(compressionParameter_unsupported);
|
||||
}
|
||||
|
||||
static void ZSTD_startNewCompression(ZSTD_CCtx* cctx)
|
||||
{
|
||||
cctx->streamStage = zcss_init;
|
||||
cctx->pledgedSrcSizePlusOne = 0;
|
||||
}
|
||||
|
||||
/*! ZSTD_CCtx_reset() :
|
||||
* Also dumps dictionary */
|
||||
void ZSTD_CCtx_reset(ZSTD_CCtx* cctx)
|
||||
{
|
||||
ZSTD_startNewCompression(cctx);
|
||||
cctx->cdict = NULL;
|
||||
}
|
||||
|
||||
/** ZSTD_checkCParams() :
|
||||
control CParam values remain within authorized range.
|
||||
@return : 0, or an error code if one value is beyond authorized range */
|
||||
size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
# define CLAMPCHECK(val,min,max) { if ((val<min) | (val>max)) return ERROR(compressionParameter_unsupported); }
|
||||
CLAMPCHECK(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
|
||||
CLAMPCHECK(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
|
||||
CLAMPCHECK(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
|
||||
@@ -214,6 +470,24 @@ size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** ZSTD_clampCParams() :
|
||||
* make CParam values within valid range.
|
||||
* @return : valid CParams */
|
||||
static ZSTD_compressionParameters ZSTD_clampCParams(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
# define CLAMP(val,min,max) { \
|
||||
if (val<min) val=min; \
|
||||
else if (val>max) val=max; \
|
||||
}
|
||||
CLAMP(cParams.windowLog, ZSTD_WINDOWLOG_MIN, ZSTD_WINDOWLOG_MAX);
|
||||
CLAMP(cParams.chainLog, ZSTD_CHAINLOG_MIN, ZSTD_CHAINLOG_MAX);
|
||||
CLAMP(cParams.hashLog, ZSTD_HASHLOG_MIN, ZSTD_HASHLOG_MAX);
|
||||
CLAMP(cParams.searchLog, ZSTD_SEARCHLOG_MIN, ZSTD_SEARCHLOG_MAX);
|
||||
CLAMP(cParams.searchLength, ZSTD_SEARCHLENGTH_MIN, ZSTD_SEARCHLENGTH_MAX);
|
||||
CLAMP(cParams.targetLength, ZSTD_TARGETLENGTH_MIN, ZSTD_TARGETLENGTH_MAX);
|
||||
if ((U32)(cParams.strategy) > (U32)ZSTD_btultra) cParams.strategy = ZSTD_btultra;
|
||||
return cParams;
|
||||
}
|
||||
|
||||
/** ZSTD_cycleLog() :
|
||||
* condition for correct operation : hashLog > 1 */
|
||||
@@ -223,14 +497,15 @@ static U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)
|
||||
return hashLog - btScale;
|
||||
}
|
||||
|
||||
/** ZSTD_adjustCParams() :
|
||||
/** ZSTD_adjustCParams_internal() :
|
||||
optimize `cPar` for a given input (`srcSize` and `dictSize`).
|
||||
mostly downsizing to reduce memory consumption and initialization.
|
||||
Both `srcSize` and `dictSize` are optional (use 0 if unknown),
|
||||
but if both are 0, no optimization can be done.
|
||||
Note : cPar is considered validated at this stage. Use ZSTD_checkParams() to ensure that. */
|
||||
ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
|
||||
ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
|
||||
{
|
||||
assert(ZSTD_checkCParams(cPar)==0);
|
||||
if (srcSize+dictSize == 0) return cPar; /* no size information available : no adjustment */
|
||||
|
||||
/* resize params, to use less memory when necessary */
|
||||
@@ -250,10 +525,16 @@ ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, u
|
||||
return cPar;
|
||||
}
|
||||
|
||||
ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize)
|
||||
{
|
||||
cPar = ZSTD_clampCParams(cPar);
|
||||
return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
||||
U32 const divider = (cParams.searchLength==3) ? 3 : 4;
|
||||
size_t const maxNbSeq = blockSize / divider;
|
||||
size_t const tokenSpace = blockSize + 11*maxNbSeq;
|
||||
@@ -272,26 +553,48 @@ size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams)
|
||||
size_t const optSpace = ((cParams.strategy == ZSTD_btopt) || (cParams.strategy == ZSTD_btultra)) ? optBudget : 0;
|
||||
size_t const neededSpace = entropySpace + tableSpace + tokenSpace + optSpace;
|
||||
|
||||
DEBUGLOG(5, "sizeof(ZSTD_CCtx) : %u", (U32)sizeof(ZSTD_CCtx));
|
||||
DEBUGLOG(5, "estimate workSpace : %u", (U32)neededSpace);
|
||||
return sizeof(ZSTD_CCtx) + neededSpace;
|
||||
}
|
||||
|
||||
|
||||
static U32 ZSTD_equivalentParams(ZSTD_parameters param1, ZSTD_parameters param2)
|
||||
size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
return (param1.cParams.hashLog == param2.cParams.hashLog)
|
||||
& (param1.cParams.chainLog == param2.cParams.chainLog)
|
||||
& (param1.cParams.strategy == param2.cParams.strategy) /* opt parser space */
|
||||
& ((param1.cParams.searchLength==3) == (param2.cParams.searchLength==3)); /* hashlog3 space */
|
||||
size_t const CCtxSize = ZSTD_estimateCCtxSize(cParams);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog);
|
||||
size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
|
||||
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
|
||||
size_t const streamingSize = inBuffSize + outBuffSize;
|
||||
|
||||
return CCtxSize + streamingSize;
|
||||
}
|
||||
|
||||
|
||||
static U32 ZSTD_equivalentParams(ZSTD_compressionParameters cParams1,
|
||||
ZSTD_compressionParameters cParams2)
|
||||
{
|
||||
U32 bslog1 = MIN(cParams1.windowLog, ZSTD_BLOCKSIZELOG_MAX);
|
||||
U32 bslog2 = MIN(cParams2.windowLog, ZSTD_BLOCKSIZELOG_MAX);
|
||||
return (bslog1 == bslog2) /* same block size */
|
||||
& (cParams1.hashLog == cParams2.hashLog)
|
||||
& (cParams1.chainLog == cParams2.chainLog)
|
||||
& (cParams1.strategy == cParams2.strategy) /* opt parser space */
|
||||
& ((cParams1.searchLength==3) == (cParams2.searchLength==3)); /* hashlog3 space */
|
||||
}
|
||||
|
||||
/*! ZSTD_continueCCtx() :
|
||||
reuse CCtx without reset (note : requires no dictionary) */
|
||||
static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 frameContentSize)
|
||||
* reuse CCtx without reset (note : requires no dictionary) */
|
||||
static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 pledgedSrcSize)
|
||||
{
|
||||
U32 const end = (U32)(cctx->nextSrc - cctx->base);
|
||||
cctx->params = params;
|
||||
cctx->frameContentSize = frameContentSize;
|
||||
DEBUGLOG(5, "continue mode");
|
||||
cctx->appliedParams = params;
|
||||
cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
||||
cctx->consumedSrcSize = 0;
|
||||
if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
cctx->appliedParams.fParams.contentSizeFlag = 0;
|
||||
DEBUGLOG(5, "pledged content size : %u ; flag : %u",
|
||||
(U32)pledgedSrcSize, cctx->appliedParams.fParams.contentSizeFlag);
|
||||
cctx->lowLimit = end;
|
||||
cctx->dictLimit = end;
|
||||
cctx->nextToUpdate = end+1;
|
||||
@@ -304,33 +607,38 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 fra
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset, ZSTDcrp_fullReset } ZSTD_compResetPolicy_e;
|
||||
typedef enum { ZSTDcrp_continue, ZSTDcrp_noMemset } ZSTD_compResetPolicy_e;
|
||||
|
||||
/*! ZSTD_resetCCtx_internal() :
|
||||
note : `params` must be validated */
|
||||
static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
|
||||
ZSTD_parameters params, U64 frameContentSize,
|
||||
ZSTD_compResetPolicy_e const crp)
|
||||
note : `params` are assumed fully validated at this stage */
|
||||
static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize,
|
||||
ZSTD_compResetPolicy_e const crp,
|
||||
ZSTD_buffered_policy_e const zbuff)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_resetCCtx_internal \n");
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
|
||||
if (crp == ZSTDcrp_continue)
|
||||
if (ZSTD_equivalentParams(params, zc->params)) {
|
||||
DEBUGLOG(5, "ZSTD_equivalentParams()==1 \n");
|
||||
if (crp == ZSTDcrp_continue) {
|
||||
if (ZSTD_equivalentParams(params.cParams, zc->appliedParams.cParams)) {
|
||||
DEBUGLOG(5, "ZSTD_equivalentParams()==1");
|
||||
zc->fseCTables_ready = 0;
|
||||
zc->hufCTable_repeatMode = HUF_repeat_none;
|
||||
return ZSTD_continueCCtx(zc, params, frameContentSize);
|
||||
}
|
||||
return ZSTD_continueCCtx(zc, params, pledgedSrcSize);
|
||||
} }
|
||||
|
||||
{ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog);
|
||||
{ size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << params.cParams.windowLog);
|
||||
U32 const divider = (params.cParams.searchLength==3) ? 3 : 4;
|
||||
size_t const maxNbSeq = blockSize / divider;
|
||||
size_t const tokenSpace = blockSize + 11*maxNbSeq;
|
||||
size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ? 0 : (1 << params.cParams.chainLog);
|
||||
size_t const chainSize = (params.cParams.strategy == ZSTD_fast) ?
|
||||
0 : (1 << params.cParams.chainLog);
|
||||
size_t const hSize = ((size_t)1) << params.cParams.hashLog;
|
||||
U32 const hashLog3 = (params.cParams.searchLength>3) ? 0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
|
||||
U32 const hashLog3 = (params.cParams.searchLength>3) ?
|
||||
0 : MIN(ZSTD_HASHLOG3_MAX, params.cParams.windowLog);
|
||||
size_t const h3Size = ((size_t)1) << hashLog3;
|
||||
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
||||
size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0;
|
||||
size_t const buffInSize = (zbuff==ZSTDb_buffered) ? ((size_t)1 << params.cParams.windowLog) + blockSize : 0;
|
||||
void* ptr;
|
||||
|
||||
/* Check if workSpace is large enough, alloc a new one if needed */
|
||||
@@ -339,11 +647,20 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
|
||||
+ entropyScratchSpace_size;
|
||||
size_t const optPotentialSpace = ((MaxML+1) + (MaxLL+1) + (MaxOff+1) + (1<<Litbits)) * sizeof(U32)
|
||||
+ (ZSTD_OPT_NUM+1) * (sizeof(ZSTD_match_t)+sizeof(ZSTD_optimal_t));
|
||||
size_t const optSpace = ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) ? optPotentialSpace : 0;
|
||||
size_t const neededSpace = entropySpace + optSpace + tableSpace + tokenSpace;
|
||||
if (zc->workSpaceSize < neededSpace) {
|
||||
size_t const optSpace = ( (params.cParams.strategy == ZSTD_btopt)
|
||||
|| (params.cParams.strategy == ZSTD_btultra)) ?
|
||||
optPotentialSpace : 0;
|
||||
size_t const bufferSpace = buffInSize + buffOutSize;
|
||||
size_t const neededSpace = entropySpace + optSpace + tableSpace
|
||||
+ tokenSpace + bufferSpace;
|
||||
|
||||
if (zc->workSpaceSize < neededSpace) { /* too small : resize /*/
|
||||
DEBUGLOG(5, "Need to update workSpaceSize from %uK to %uK \n",
|
||||
(unsigned)zc->workSpaceSize>>10, (unsigned)neededSpace>>10);
|
||||
(unsigned)zc->workSpaceSize>>10,
|
||||
(unsigned)neededSpace>>10);
|
||||
/* static cctx : no resize, error out */
|
||||
if (zc->staticSize) return ERROR(memory_allocation);
|
||||
|
||||
zc->workSpaceSize = 0;
|
||||
ZSTD_free(zc->workSpace, zc->customMem);
|
||||
zc->workSpace = ZSTD_malloc(neededSpace, zc->customMem);
|
||||
@@ -365,11 +682,14 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
|
||||
} }
|
||||
|
||||
/* init params */
|
||||
zc->params = params;
|
||||
zc->blockSize = blockSize;
|
||||
DEBUGLOG(5, "blockSize = %uK \n", (U32)blockSize>>10);
|
||||
zc->frameContentSize = frameContentSize;
|
||||
zc->appliedParams = params;
|
||||
zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;
|
||||
zc->consumedSrcSize = 0;
|
||||
if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)
|
||||
zc->appliedParams.fParams.contentSizeFlag = 0;
|
||||
DEBUGLOG(5, "pledged content size : %u ; flag : %u",
|
||||
(U32)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);
|
||||
zc->blockSize = blockSize;
|
||||
|
||||
XXH64_reset(&zc->xxhState, 0);
|
||||
zc->stage = ZSTDcs_init;
|
||||
@@ -397,7 +717,7 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
|
||||
|
||||
/* opt parser space */
|
||||
if ((params.cParams.strategy == ZSTD_btopt) || (params.cParams.strategy == ZSTD_btultra)) {
|
||||
DEBUGLOG(5, "reserving optimal parser space ");
|
||||
DEBUGLOG(5, "reserving optimal parser space");
|
||||
assert(((size_t)ptr & 3) == 0); /* ensure ptr is properly aligned */
|
||||
zc->seqStore.litFreq = (U32*)ptr;
|
||||
zc->seqStore.litLengthFreq = zc->seqStore.litFreq + (1<<Litbits);
|
||||
@@ -425,6 +745,13 @@ static size_t ZSTD_resetCCtx_internal (ZSTD_CCtx* zc,
|
||||
zc->seqStore.mlCode = zc->seqStore.llCode + maxNbSeq;
|
||||
zc->seqStore.ofCode = zc->seqStore.mlCode + maxNbSeq;
|
||||
zc->seqStore.litStart = zc->seqStore.ofCode + maxNbSeq;
|
||||
ptr = zc->seqStore.litStart + blockSize;
|
||||
|
||||
/* buffers */
|
||||
zc->inBuffSize = buffInSize;
|
||||
zc->inBuff = (char*)ptr;
|
||||
zc->outBuffSize = buffOutSize;
|
||||
zc->outBuff = zc->inBuff + buffInSize;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -445,22 +772,25 @@ void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {
|
||||
* Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).
|
||||
* pledgedSrcSize=0 means "empty" if fParams.contentSizeFlag=1
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx,
|
||||
ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize)
|
||||
static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
|
||||
const ZSTD_CCtx* srcCCtx,
|
||||
ZSTD_frameParameters fParams,
|
||||
unsigned long long pledgedSrcSize,
|
||||
ZSTD_buffered_policy_e zbuff)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_copyCCtx_internal \n");
|
||||
DEBUGLOG(5, "ZSTD_copyCCtx_internal");
|
||||
if (srcCCtx->stage!=ZSTDcs_init) return ERROR(stage_wrong);
|
||||
|
||||
memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));
|
||||
{ ZSTD_parameters params = srcCCtx->params;
|
||||
{ ZSTD_parameters params = srcCCtx->appliedParams;
|
||||
params.fParams = fParams;
|
||||
DEBUGLOG(5, "ZSTD_resetCCtx_internal : dictIDFlag : %u \n", !fParams.noDictIDFlag);
|
||||
ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize, ZSTDcrp_noMemset);
|
||||
ZSTD_resetCCtx_internal(dstCCtx, params, pledgedSrcSize,
|
||||
ZSTDcrp_noMemset, zbuff);
|
||||
}
|
||||
|
||||
/* copy tables */
|
||||
{ size_t const chainSize = (srcCCtx->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->params.cParams.chainLog);
|
||||
size_t const hSize = (size_t)1 << srcCCtx->params.cParams.hashLog;
|
||||
{ size_t const chainSize = (srcCCtx->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << srcCCtx->appliedParams.cParams.chainLog);
|
||||
size_t const hSize = (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;
|
||||
size_t const h3Size = (size_t)1 << srcCCtx->hashLog3;
|
||||
size_t const tableSpace = (chainSize + hSize + h3Size) * sizeof(U32);
|
||||
assert((U32*)dstCCtx->chainTable == (U32*)dstCCtx->hashTable + hSize); /* chainTable must follow hashTable */
|
||||
@@ -502,9 +832,11 @@ size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx,
|
||||
size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
|
||||
ZSTD_buffered_policy_e const zbuff = (ZSTD_buffered_policy_e)(srcCCtx->inBuffSize>0);
|
||||
ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);
|
||||
fParams.contentSizeFlag = pledgedSrcSize>0;
|
||||
|
||||
return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, fParams, pledgedSrcSize);
|
||||
return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx, fParams, pledgedSrcSize, zbuff);
|
||||
}
|
||||
|
||||
|
||||
@@ -523,10 +855,10 @@ static void ZSTD_reduceTable (U32* const table, U32 const size, U32 const reduce
|
||||
* rescale all indexes to avoid future overflow (indexes are U32) */
|
||||
static void ZSTD_reduceIndex (ZSTD_CCtx* zc, const U32 reducerValue)
|
||||
{
|
||||
{ U32 const hSize = 1 << zc->params.cParams.hashLog;
|
||||
{ U32 const hSize = 1 << zc->appliedParams.cParams.hashLog;
|
||||
ZSTD_reduceTable(zc->hashTable, hSize, reducerValue); }
|
||||
|
||||
{ U32 const chainSize = (zc->params.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->params.cParams.chainLog);
|
||||
{ U32 const chainSize = (zc->appliedParams.cParams.strategy == ZSTD_fast) ? 0 : (1 << zc->appliedParams.cParams.chainLog);
|
||||
ZSTD_reduceTable(zc->chainTable, chainSize, reducerValue); }
|
||||
|
||||
{ U32 const h3Size = (zc->hashLog3) ? 1 << zc->hashLog3 : 0;
|
||||
@@ -564,10 +896,11 @@ static size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void
|
||||
case 2: /* 2 - 2 - 12 */
|
||||
MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));
|
||||
break;
|
||||
default: /*note : should not be necessary : flSize is within {1,2,3} */
|
||||
case 3: /* 2 - 2 - 20 */
|
||||
MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));
|
||||
break;
|
||||
default: /* not necessary : flSize is {1,2,3} */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
memcpy(ostart + flSize, src, srcSize);
|
||||
@@ -589,10 +922,11 @@ static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, cons
|
||||
case 2: /* 2 - 2 - 12 */
|
||||
MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));
|
||||
break;
|
||||
default: /*note : should not be necessary : flSize is necessarily within {1,2,3} */
|
||||
case 3: /* 2 - 2 - 20 */
|
||||
MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));
|
||||
break;
|
||||
default: /* not necessary : flSize is {1,2,3} */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
ostart[flSize] = *(const BYTE*)src;
|
||||
@@ -622,7 +956,7 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
|
||||
|
||||
if (dstCapacity < lhSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
|
||||
{ HUF_repeat repeat = zc->hufCTable_repeatMode;
|
||||
int const preferRepeat = zc->params.cParams.strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
|
||||
int const preferRepeat = zc->appliedParams.cParams.strategy < ZSTD_lazy ? srcSize <= 1024 : 0;
|
||||
if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;
|
||||
cLitSize = singleStream ? HUF_compress1X_repeat(ostart+lhSize, dstCapacity-lhSize, src, srcSize, 255, 11,
|
||||
zc->entropyScratchSpace, entropyScratchSpace_size, zc->hufCTable, &repeat, preferRepeat)
|
||||
@@ -654,13 +988,14 @@ static size_t ZSTD_compressLiterals (ZSTD_CCtx* zc,
|
||||
MEM_writeLE32(ostart, lhc);
|
||||
break;
|
||||
}
|
||||
default: /* should not be necessary, lhSize is only {3,4,5} */
|
||||
case 5: /* 2 - 2 - 18 - 18 */
|
||||
{ U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);
|
||||
MEM_writeLE32(ostart, lhc);
|
||||
ostart[4] = (BYTE)(cLitSize >> 10);
|
||||
break;
|
||||
}
|
||||
default: /* not possible : lhSize is {3,4,5} */
|
||||
assert(0);
|
||||
}
|
||||
return lhSize+cLitSize;
|
||||
}
|
||||
@@ -711,7 +1046,7 @@ MEM_STATIC size_t ZSTD_compressSequences (ZSTD_CCtx* zc,
|
||||
void* dst, size_t dstCapacity,
|
||||
size_t srcSize)
|
||||
{
|
||||
const int longOffsets = zc->params.cParams.windowLog > STREAM_ACCUMULATOR_MIN;
|
||||
const int longOffsets = zc->appliedParams.cParams.windowLog > STREAM_ACCUMULATOR_MIN;
|
||||
const seqStore_t* seqStorePtr = &(zc->seqStore);
|
||||
U32 count[MaxSeq+1];
|
||||
S16 norm[MaxSeq+1];
|
||||
@@ -916,12 +1251,6 @@ _check_compressibility:
|
||||
return op - ostart;
|
||||
}
|
||||
|
||||
#if 0 /* for debug */
|
||||
# define STORESEQ_DEBUG
|
||||
#include <stdio.h> /* fprintf */
|
||||
U32 g_startDebug = 0;
|
||||
const BYTE* g_start = NULL;
|
||||
#endif
|
||||
|
||||
/*! ZSTD_storeSeq() :
|
||||
Store a sequence (literal length, literals, offset code and match length code) into seqStore_t.
|
||||
@@ -930,16 +1259,16 @@ const BYTE* g_start = NULL;
|
||||
*/
|
||||
MEM_STATIC void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const void* literals, U32 offsetCode, size_t matchCode)
|
||||
{
|
||||
#ifdef STORESEQ_DEBUG
|
||||
if (g_startDebug) {
|
||||
const U32 pos = (U32)((const BYTE*)literals - g_start);
|
||||
if (g_start==NULL) g_start = (const BYTE*)literals;
|
||||
if ((pos > 1895000) && (pos < 1895300))
|
||||
DEBUGLOG(5, "Cpos %6u :%5u literals & match %3u bytes at distance %6u \n",
|
||||
pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
||||
}
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG >= 6)
|
||||
static const BYTE* g_start = NULL;
|
||||
U32 const pos = (U32)((const BYTE*)literals - g_start);
|
||||
if (g_start==NULL) g_start = (const BYTE*)literals;
|
||||
if ((pos > 0) && (pos < 1000000000))
|
||||
DEBUGLOG(6, "Cpos %6u :%5u literals & match %3u bytes at distance %6u",
|
||||
pos, (U32)litLength, (U32)matchCode+MINMATCH, (U32)offsetCode);
|
||||
#endif
|
||||
/* copy Literals */
|
||||
assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + 128 KB);
|
||||
ZSTD_wildcopy(seqStorePtr->lit, literals, litLength);
|
||||
seqStorePtr->lit += litLength;
|
||||
|
||||
@@ -1113,7 +1442,7 @@ static size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)
|
||||
static void ZSTD_fillHashTable (ZSTD_CCtx* zc, const void* end, const U32 mls)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
U32 const hBits = zc->params.cParams.hashLog;
|
||||
U32 const hBits = zc->appliedParams.cParams.hashLog;
|
||||
const BYTE* const base = zc->base;
|
||||
const BYTE* ip = base + zc->nextToUpdate;
|
||||
const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
|
||||
@@ -1132,7 +1461,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
|
||||
const U32 mls)
|
||||
{
|
||||
U32* const hashTable = cctx->hashTable;
|
||||
U32 const hBits = cctx->params.cParams.hashLog;
|
||||
U32 const hBits = cctx->appliedParams.cParams.hashLog;
|
||||
seqStore_t* seqStorePtr = &(cctx->seqStore);
|
||||
const BYTE* const base = cctx->base;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
@@ -1217,7 +1546,7 @@ void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* cctx,
|
||||
static void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
@@ -1238,7 +1567,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const U32 mls)
|
||||
{
|
||||
U32* hashTable = ctx->hashTable;
|
||||
const U32 hBits = ctx->params.cParams.hashLog;
|
||||
const U32 hBits = ctx->appliedParams.cParams.hashLog;
|
||||
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
||||
const BYTE* const base = ctx->base;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
@@ -1331,7 +1660,7 @@ static void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
U32 const mls = ctx->params.cParams.searchLength;
|
||||
U32 const mls = ctx->appliedParams.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
@@ -1353,9 +1682,9 @@ static void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
|
||||
static void ZSTD_fillDoubleHashTable (ZSTD_CCtx* cctx, const void* end, const U32 mls)
|
||||
{
|
||||
U32* const hashLarge = cctx->hashTable;
|
||||
U32 const hBitsL = cctx->params.cParams.hashLog;
|
||||
U32 const hBitsL = cctx->appliedParams.cParams.hashLog;
|
||||
U32* const hashSmall = cctx->chainTable;
|
||||
U32 const hBitsS = cctx->params.cParams.chainLog;
|
||||
U32 const hBitsS = cctx->appliedParams.cParams.chainLog;
|
||||
const BYTE* const base = cctx->base;
|
||||
const BYTE* ip = base + cctx->nextToUpdate;
|
||||
const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;
|
||||
@@ -1375,9 +1704,9 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
|
||||
const U32 mls)
|
||||
{
|
||||
U32* const hashLong = cctx->hashTable;
|
||||
const U32 hBitsL = cctx->params.cParams.hashLog;
|
||||
const U32 hBitsL = cctx->appliedParams.cParams.hashLog;
|
||||
U32* const hashSmall = cctx->chainTable;
|
||||
const U32 hBitsS = cctx->params.cParams.chainLog;
|
||||
const U32 hBitsS = cctx->appliedParams.cParams.chainLog;
|
||||
seqStore_t* seqStorePtr = &(cctx->seqStore);
|
||||
const BYTE* const base = cctx->base;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
@@ -1487,7 +1816,7 @@ void ZSTD_compressBlock_doubleFast_generic(ZSTD_CCtx* cctx,
|
||||
|
||||
static void ZSTD_compressBlock_doubleFast(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
|
||||
{
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
@@ -1508,9 +1837,9 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const U32 mls)
|
||||
{
|
||||
U32* const hashLong = ctx->hashTable;
|
||||
U32 const hBitsL = ctx->params.cParams.hashLog;
|
||||
U32 const hBitsL = ctx->appliedParams.cParams.hashLog;
|
||||
U32* const hashSmall = ctx->chainTable;
|
||||
U32 const hBitsS = ctx->params.cParams.chainLog;
|
||||
U32 const hBitsS = ctx->appliedParams.cParams.chainLog;
|
||||
seqStore_t* seqStorePtr = &(ctx->seqStore);
|
||||
const BYTE* const base = ctx->base;
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
@@ -1637,7 +1966,7 @@ static void ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_CCtx* ctx,
|
||||
static void ZSTD_compressBlock_doubleFast_extDict(ZSTD_CCtx* ctx,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
U32 const mls = ctx->params.cParams.searchLength;
|
||||
U32 const mls = ctx->appliedParams.cParams.searchLength;
|
||||
switch(mls)
|
||||
{
|
||||
default: /* includes case 3 */
|
||||
@@ -1663,10 +1992,10 @@ static U32 ZSTD_insertBt1(ZSTD_CCtx* zc, const BYTE* const ip, const U32 mls, co
|
||||
U32 extDict)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
U32 const hashLog = zc->params.cParams.hashLog;
|
||||
U32 const hashLog = zc->appliedParams.cParams.hashLog;
|
||||
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
|
||||
U32* const bt = zc->chainTable;
|
||||
U32 const btLog = zc->params.cParams.chainLog - 1;
|
||||
U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
|
||||
U32 const btMask = (1 << btLog) - 1;
|
||||
U32 matchIndex = hashTable[h];
|
||||
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
||||
@@ -1768,10 +2097,10 @@ static size_t ZSTD_insertBtAndFindBestMatch (
|
||||
U32 extDict)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
U32 const hashLog = zc->params.cParams.hashLog;
|
||||
U32 const hashLog = zc->appliedParams.cParams.hashLog;
|
||||
size_t const h = ZSTD_hashPtr(ip, hashLog, mls);
|
||||
U32* const bt = zc->chainTable;
|
||||
U32 const btLog = zc->params.cParams.chainLog - 1;
|
||||
U32 const btLog = zc->appliedParams.cParams.chainLog - 1;
|
||||
U32 const btMask = (1 << btLog) - 1;
|
||||
U32 matchIndex = hashTable[h];
|
||||
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
||||
@@ -1931,9 +2260,9 @@ FORCE_INLINE
|
||||
U32 ZSTD_insertAndFindFirstIndex (ZSTD_CCtx* zc, const BYTE* ip, U32 mls)
|
||||
{
|
||||
U32* const hashTable = zc->hashTable;
|
||||
const U32 hashLog = zc->params.cParams.hashLog;
|
||||
const U32 hashLog = zc->appliedParams.cParams.hashLog;
|
||||
U32* const chainTable = zc->chainTable;
|
||||
const U32 chainMask = (1 << zc->params.cParams.chainLog) - 1;
|
||||
const U32 chainMask = (1 << zc->appliedParams.cParams.chainLog) - 1;
|
||||
const BYTE* const base = zc->base;
|
||||
const U32 target = (U32)(ip - base);
|
||||
U32 idx = zc->nextToUpdate;
|
||||
@@ -1959,7 +2288,7 @@ size_t ZSTD_HcFindBestMatch_generic (
|
||||
const U32 maxNbAttempts, const U32 mls, const U32 extDict)
|
||||
{
|
||||
U32* const chainTable = zc->chainTable;
|
||||
const U32 chainSize = (1 << zc->params.cParams.chainLog);
|
||||
const U32 chainSize = (1 << zc->appliedParams.cParams.chainLog);
|
||||
const U32 chainMask = chainSize-1;
|
||||
const BYTE* const base = zc->base;
|
||||
const BYTE* const dictBase = zc->dictBase;
|
||||
@@ -2053,8 +2382,8 @@ void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const ilimit = iend - 8;
|
||||
const BYTE* const base = ctx->base + ctx->dictLimit;
|
||||
|
||||
U32 const maxSearches = 1 << ctx->params.cParams.searchLog;
|
||||
U32 const mls = ctx->params.cParams.searchLength;
|
||||
U32 const maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
|
||||
U32 const mls = ctx->appliedParams.cParams.searchLength;
|
||||
|
||||
typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
|
||||
size_t* offsetPtr,
|
||||
@@ -2221,8 +2550,8 @@ void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
const BYTE* const dictStart = dictBase + ctx->lowLimit;
|
||||
|
||||
const U32 maxSearches = 1 << ctx->params.cParams.searchLog;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
const U32 maxSearches = 1 << ctx->appliedParams.cParams.searchLog;
|
||||
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
||||
|
||||
typedef size_t (*searchMax_f)(ZSTD_CCtx* zc, const BYTE* ip, const BYTE* iLimit,
|
||||
size_t* offsetPtr,
|
||||
@@ -2440,26 +2769,32 @@ static void ZSTD_compressBlock_btultra_extDict(ZSTD_CCtx* ctx, const void* src,
|
||||
}
|
||||
|
||||
|
||||
/* ZSTD_selectBlockCompressor() :
|
||||
* assumption : strat is a valid strategy */
|
||||
typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
|
||||
|
||||
static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
|
||||
{
|
||||
static const ZSTD_blockCompressor blockCompressor[2][8] = {
|
||||
{ ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
|
||||
static const ZSTD_blockCompressor blockCompressor[2][(unsigned)ZSTD_btultra+1] = {
|
||||
{ ZSTD_compressBlock_fast /* default for 0 */,
|
||||
ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, ZSTD_compressBlock_greedy,
|
||||
ZSTD_compressBlock_lazy, ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2,
|
||||
ZSTD_compressBlock_btopt, ZSTD_compressBlock_btultra },
|
||||
{ ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict,
|
||||
{ ZSTD_compressBlock_fast_extDict /* default for 0 */,
|
||||
ZSTD_compressBlock_fast_extDict, ZSTD_compressBlock_doubleFast_extDict, ZSTD_compressBlock_greedy_extDict,
|
||||
ZSTD_compressBlock_lazy_extDict,ZSTD_compressBlock_lazy2_extDict, ZSTD_compressBlock_btlazy2_extDict,
|
||||
ZSTD_compressBlock_btopt_extDict, ZSTD_compressBlock_btultra_extDict }
|
||||
};
|
||||
ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);
|
||||
assert((U32)strat >= (U32)ZSTD_fast);
|
||||
assert((U32)strat <= (U32)ZSTD_btultra);
|
||||
|
||||
return blockCompressor[extDict][(U32)strat];
|
||||
return blockCompressor[extDict!=0][(U32)strat];
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->params.cParams.strategy, zc->lowLimit < zc->dictLimit);
|
||||
ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, zc->lowLimit < zc->dictLimit);
|
||||
const BYTE* const base = zc->base;
|
||||
const BYTE* const istart = (const BYTE*)src;
|
||||
const U32 current = (U32)(istart-base);
|
||||
@@ -2472,14 +2807,14 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCa
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_compress_generic() :
|
||||
/*! ZSTD_compress_frameChunk() :
|
||||
* Compress a chunk of data into one or multiple blocks.
|
||||
* 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
|
||||
*/
|
||||
static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
||||
static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
U32 lastFrameChunk)
|
||||
@@ -2489,9 +2824,9 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
BYTE* const ostart = (BYTE*)dst;
|
||||
BYTE* op = ostart;
|
||||
U32 const maxDist = 1 << cctx->params.cParams.windowLog;
|
||||
U32 const maxDist = 1 << cctx->appliedParams.cParams.windowLog;
|
||||
|
||||
if (cctx->params.fParams.checksumFlag && srcSize)
|
||||
if (cctx->appliedParams.fParams.checksumFlag && srcSize)
|
||||
XXH64_update(&cctx->xxhState, src, srcSize);
|
||||
|
||||
while (remaining) {
|
||||
@@ -2504,9 +2839,9 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
||||
|
||||
/* preemptive overflow correction */
|
||||
if (cctx->lowLimit > (3U<<29)) {
|
||||
U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->params.cParams.hashLog, cctx->params.cParams.strategy)) - 1;
|
||||
U32 const cycleMask = (1 << ZSTD_cycleLog(cctx->appliedParams.cParams.hashLog, cctx->appliedParams.cParams.strategy)) - 1;
|
||||
U32 const current = (U32)(ip - cctx->base);
|
||||
U32 const newCurrent = (current & cycleMask) + (1 << cctx->params.cParams.windowLog);
|
||||
U32 const newCurrent = (current & cycleMask) + (1 << cctx->appliedParams.cParams.windowLog);
|
||||
U32 const correction = current - newCurrent;
|
||||
ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_64 <= 30);
|
||||
ZSTD_reduceIndex(cctx, correction);
|
||||
@@ -2566,7 +2901,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
||||
size_t pos;
|
||||
|
||||
if (dstCapacity < ZSTD_frameHeaderSize_max) return ERROR(dstSize_tooSmall);
|
||||
DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u \n",
|
||||
DEBUGLOG(5, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u",
|
||||
!params.fParams.noDictIDFlag, dictID, dictIDSizeCode);
|
||||
|
||||
MEM_writeLE32(dst, ZSTD_MAGICNUMBER);
|
||||
@@ -2574,7 +2909,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
||||
if (!singleSegment) op[pos++] = windowLogByte;
|
||||
switch(dictIDSizeCode)
|
||||
{
|
||||
default: /* impossible */
|
||||
default: assert(0); /* impossible */
|
||||
case 0 : break;
|
||||
case 1 : op[pos] = (BYTE)(dictID); pos++; break;
|
||||
case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break;
|
||||
@@ -2582,7 +2917,7 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
|
||||
}
|
||||
switch(fcsCode)
|
||||
{
|
||||
default: /* impossible */
|
||||
default: assert(0); /* impossible */
|
||||
case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break;
|
||||
case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;
|
||||
case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;
|
||||
@@ -2603,7 +2938,8 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
||||
if (cctx->stage==ZSTDcs_created) return ERROR(stage_wrong); /* missing init (ZSTD_compressBegin) */
|
||||
|
||||
if (frame && (cctx->stage==ZSTDcs_init)) {
|
||||
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, cctx->frameContentSize, cctx->dictID);
|
||||
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams,
|
||||
cctx->pledgedSrcSizePlusOne-1, cctx->dictID);
|
||||
if (ZSTD_isError(fhSize)) return fhSize;
|
||||
dstCapacity -= fhSize;
|
||||
dst = (char*)dst + fhSize;
|
||||
@@ -2633,7 +2969,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
|
||||
|
||||
if (srcSize) {
|
||||
size_t const cSize = frame ?
|
||||
ZSTD_compress_generic (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
||||
ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :
|
||||
ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
cctx->consumedSrcSize += srcSize;
|
||||
@@ -2651,14 +2987,18 @@ size_t ZSTD_compressContinue (ZSTD_CCtx* cctx,
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_getBlockSizeMax(ZSTD_CCtx* cctx)
|
||||
size_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)
|
||||
{
|
||||
return MIN (ZSTD_BLOCKSIZE_ABSOLUTEMAX, 1 << cctx->params.cParams.windowLog);
|
||||
U32 const cLevel = cctx->compressionLevel;
|
||||
ZSTD_compressionParameters cParams = (cLevel == ZSTD_CLEVEL_CUSTOM) ?
|
||||
cctx->appliedParams.cParams :
|
||||
ZSTD_getCParams(cLevel, 0, 0);
|
||||
return MIN (ZSTD_BLOCKSIZE_MAX, 1 << cParams.windowLog);
|
||||
}
|
||||
|
||||
size_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
size_t const blockSizeMax = ZSTD_getBlockSizeMax(cctx);
|
||||
size_t const blockSizeMax = ZSTD_getBlockSize(cctx);
|
||||
if (srcSize > blockSizeMax) return ERROR(srcSize_wrong);
|
||||
return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);
|
||||
}
|
||||
@@ -2682,32 +3022,32 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_CCtx* zc, const void* src, size_t
|
||||
zc->nextSrc = iend;
|
||||
if (srcSize <= HASH_READ_SIZE) return 0;
|
||||
|
||||
switch(zc->params.cParams.strategy)
|
||||
switch(zc->appliedParams.cParams.strategy)
|
||||
{
|
||||
case ZSTD_fast:
|
||||
ZSTD_fillHashTable (zc, iend, zc->params.cParams.searchLength);
|
||||
ZSTD_fillHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
|
||||
break;
|
||||
|
||||
case ZSTD_dfast:
|
||||
ZSTD_fillDoubleHashTable (zc, iend, zc->params.cParams.searchLength);
|
||||
ZSTD_fillDoubleHashTable (zc, iend, zc->appliedParams.cParams.searchLength);
|
||||
break;
|
||||
|
||||
case ZSTD_greedy:
|
||||
case ZSTD_lazy:
|
||||
case ZSTD_lazy2:
|
||||
if (srcSize >= HASH_READ_SIZE)
|
||||
ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->params.cParams.searchLength);
|
||||
ZSTD_insertAndFindFirstIndex(zc, iend-HASH_READ_SIZE, zc->appliedParams.cParams.searchLength);
|
||||
break;
|
||||
|
||||
case ZSTD_btlazy2:
|
||||
case ZSTD_btopt:
|
||||
case ZSTD_btultra:
|
||||
if (srcSize >= HASH_READ_SIZE)
|
||||
ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->params.cParams.searchLog, zc->params.cParams.searchLength);
|
||||
ZSTD_updateTree(zc, iend-HASH_READ_SIZE, iend, 1 << zc->appliedParams.cParams.searchLog, zc->appliedParams.cParams.searchLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
return ERROR(GENERIC); /* strategy doesn't exist; impossible */
|
||||
assert(0); /* not possible : not a valid strategy id */
|
||||
}
|
||||
|
||||
zc->nextToUpdate = (U32)(iend - zc->base);
|
||||
@@ -2747,7 +3087,7 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
|
||||
BYTE scratchBuffer[1<<MAX(MLFSELog,LLFSELog)];
|
||||
|
||||
dictPtr += 4; /* skip magic number */
|
||||
cctx->dictID = cctx->params.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
|
||||
cctx->dictID = cctx->appliedParams.fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr);
|
||||
dictPtr += 4;
|
||||
|
||||
{ size_t const hufHeaderSize = HUF_readCTable(cctx->hufCTable, 255, dictPtr, dictEnd-dictPtr);
|
||||
@@ -2818,28 +3158,56 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_CCtx* cctx, const void* dict, size_t
|
||||
|
||||
/** ZSTD_compress_insertDictionary() :
|
||||
* @return : 0, or an error code */
|
||||
static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
|
||||
static size_t ZSTD_compress_insertDictionary(ZSTD_CCtx* cctx,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_dictMode_e dictMode)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_compress_insertDictionary");
|
||||
if ((dict==NULL) || (dictSize<=8)) return 0;
|
||||
|
||||
/* dict as pure content */
|
||||
if ((MEM_readLE32(dict) != ZSTD_DICT_MAGIC) || (cctx->forceRawDict))
|
||||
/* dict restricted modes */
|
||||
if (dictMode==ZSTD_dm_rawContent)
|
||||
return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
|
||||
|
||||
/* dict as zstd dictionary */
|
||||
if (MEM_readLE32(dict) != ZSTD_DICT_MAGIC) {
|
||||
if (dictMode == ZSTD_dm_auto) {
|
||||
DEBUGLOG(5, "raw content dictionary detected");
|
||||
return ZSTD_loadDictionaryContent(cctx, dict, dictSize);
|
||||
}
|
||||
if (dictMode == ZSTD_dm_fullDict)
|
||||
return ERROR(dictionary_wrong);
|
||||
assert(0); /* impossible */
|
||||
}
|
||||
|
||||
/* dict as full zstd dictionary */
|
||||
return ZSTD_loadZstdDictionary(cctx, dict, dictSize);
|
||||
}
|
||||
|
||||
/*! ZSTD_compressBegin_internal() :
|
||||
* @return : 0, or an error code */
|
||||
* @return : 0, or an error code */
|
||||
static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize)
|
||||
ZSTD_dictMode_e dictMode,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params, U64 pledgedSrcSize,
|
||||
ZSTD_buffered_policy_e zbuff)
|
||||
{
|
||||
ZSTD_compResetPolicy_e const crp = dictSize ? ZSTDcrp_fullReset : ZSTDcrp_continue;
|
||||
DEBUGLOG(5, "ZSTD_compressBegin_internal");
|
||||
DEBUGLOG(5, "dict ? %s", dict ? "dict" : cdict ? "cdict" : "none");
|
||||
DEBUGLOG(5, "dictMode : %u", (U32)dictMode);
|
||||
/* params are supposed to be fully validated at this point */
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
CHECK_F(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, crp));
|
||||
return ZSTD_compress_insertDictionary(cctx, dict, dictSize);
|
||||
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
||||
|
||||
if (cdict && cdict->dictContentSize>0) {
|
||||
return ZSTD_copyCCtx_internal(cctx, cdict->refContext,
|
||||
params.fParams, pledgedSrcSize,
|
||||
zbuff);
|
||||
}
|
||||
|
||||
CHECK_F( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,
|
||||
ZSTDcrp_continue, zbuff) );
|
||||
return ZSTD_compress_insertDictionary(cctx, dict, dictSize, dictMode);
|
||||
}
|
||||
|
||||
|
||||
@@ -2851,14 +3219,16 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,
|
||||
{
|
||||
/* compression parameters verification and optimization */
|
||||
CHECK_F(ZSTD_checkCParams(params.cParams));
|
||||
return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, pledgedSrcSize);
|
||||
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
|
||||
params, pledgedSrcSize, ZSTDb_not_buffered);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
|
||||
return ZSTD_compressBegin_internal(cctx, dict, dictSize, params, 0);
|
||||
return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
|
||||
params, 0, ZSTDb_not_buffered);
|
||||
}
|
||||
|
||||
|
||||
@@ -2877,12 +3247,12 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
||||
BYTE* op = ostart;
|
||||
size_t fhSize = 0;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_writeEpilogue \n");
|
||||
DEBUGLOG(5, "ZSTD_writeEpilogue");
|
||||
if (cctx->stage == ZSTDcs_created) return ERROR(stage_wrong); /* init missing */
|
||||
|
||||
/* special case : empty frame */
|
||||
if (cctx->stage == ZSTDcs_init) {
|
||||
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->params, 0, 0);
|
||||
fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, cctx->appliedParams, 0, 0);
|
||||
if (ZSTD_isError(fhSize)) return fhSize;
|
||||
dstCapacity -= fhSize;
|
||||
op += fhSize;
|
||||
@@ -2898,7 +3268,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)
|
||||
dstCapacity -= ZSTD_blockHeaderSize;
|
||||
}
|
||||
|
||||
if (cctx->params.fParams.checksumFlag) {
|
||||
if (cctx->appliedParams.fParams.checksumFlag) {
|
||||
U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);
|
||||
if (dstCapacity<4) return ERROR(dstSize_tooSmall);
|
||||
MEM_writeLE32(op, checksum);
|
||||
@@ -2915,15 +3285,19 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t endResult;
|
||||
size_t const cSize = ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize,
|
||||
1 /* frame mode */, 1 /* last chunk */);
|
||||
size_t const cSize = ZSTD_compressContinue_internal(cctx,
|
||||
dst, dstCapacity, src, srcSize,
|
||||
1 /* frame mode */, 1 /* last chunk */);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);
|
||||
if (ZSTD_isError(endResult)) return endResult;
|
||||
if (cctx->params.fParams.contentSizeFlag) { /* control src size */
|
||||
if (cctx->frameContentSize != cctx->consumedSrcSize)
|
||||
if (cctx->appliedParams.fParams.contentSizeFlag) { /* control src size */
|
||||
DEBUGLOG(5, "end of frame : controlling src size");
|
||||
if (cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1) {
|
||||
DEBUGLOG(5, "error : pledgedSrcSize = %u, while realSrcSize = %u",
|
||||
(U32)cctx->pledgedSrcSizePlusOne-1, (U32)cctx->consumedSrcSize);
|
||||
return ERROR(srcSize_wrong);
|
||||
}
|
||||
} }
|
||||
return cSize + endResult;
|
||||
}
|
||||
|
||||
@@ -2934,7 +3308,8 @@ static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx,
|
||||
const void* dict,size_t dictSize,
|
||||
ZSTD_parameters params)
|
||||
{
|
||||
CHECK_F(ZSTD_compressBegin_internal(cctx, dict, dictSize, params, srcSize));
|
||||
CHECK_F( ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dm_auto, NULL,
|
||||
params, srcSize, ZSTDb_not_buffered) );
|
||||
return ZSTD_compressEnd(cctx, dst, dstCapacity, src, srcSize);
|
||||
}
|
||||
|
||||
@@ -2966,33 +3341,30 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, const void* src, size_t srcS
|
||||
size_t result;
|
||||
ZSTD_CCtx ctxBody;
|
||||
memset(&ctxBody, 0, sizeof(ctxBody));
|
||||
memcpy(&ctxBody.customMem, &defaultCustomMem, sizeof(ZSTD_customMem));
|
||||
ctxBody.customMem = ZSTD_defaultCMem;
|
||||
result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);
|
||||
ZSTD_free(ctxBody.workSpace, defaultCustomMem); /* can't free ctxBody itself, as it's on stack; free only heap content */
|
||||
ZSTD_free(ctxBody.workSpace, ZSTD_defaultCMem); /* can't free ctxBody itself, as it's on stack; free only heap content */
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* ===== Dictionary API ===== */
|
||||
|
||||
struct ZSTD_CDict_s {
|
||||
void* dictBuffer;
|
||||
const void* dictContent;
|
||||
size_t dictContentSize;
|
||||
ZSTD_CCtx* refContext;
|
||||
}; /* typedef'd tp ZSTD_CDict within "zstd.h" */
|
||||
|
||||
/*! ZSTD_estimateCDictSize() :
|
||||
* Estimate amount of memory that will be needed to create a dictionary with following arguments */
|
||||
size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize)
|
||||
size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize, unsigned byReference)
|
||||
{
|
||||
cParams = ZSTD_adjustCParams(cParams, 0, dictSize);
|
||||
return sizeof(ZSTD_CDict) + dictSize + ZSTD_estimateCCtxSize(cParams);
|
||||
DEBUGLOG(5, "sizeof(ZSTD_CDict) : %u", (U32)sizeof(ZSTD_CDict));
|
||||
DEBUGLOG(5, "CCtx estimate : %u", (U32)ZSTD_estimateCCtxSize(cParams));
|
||||
return sizeof(ZSTD_CDict) + ZSTD_estimateCCtxSize(cParams)
|
||||
+ (byReference ? 0 : dictSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)
|
||||
{
|
||||
if (cdict==NULL) return 0; /* support sizeof on NULL */
|
||||
DEBUGLOG(5, "sizeof(*cdict) : %u", (U32)sizeof(*cdict));
|
||||
DEBUGLOG(5, "ZSTD_sizeof_CCtx : %u", (U32)ZSTD_sizeof_CCtx(cdict->refContext));
|
||||
return ZSTD_sizeof_CCtx(cdict->refContext) + (cdict->dictBuffer ? cdict->dictContentSize : 0) + sizeof(*cdict);
|
||||
}
|
||||
|
||||
@@ -3004,13 +3376,46 @@ static ZSTD_parameters ZSTD_makeParams(ZSTD_compressionParameters cParams, ZSTD_
|
||||
return params;
|
||||
}
|
||||
|
||||
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, unsigned byReference,
|
||||
static size_t ZSTD_initCDict_internal(
|
||||
ZSTD_CDict* cdict,
|
||||
const void* dictBuffer, size_t dictSize,
|
||||
unsigned byReference, ZSTD_dictMode_e dictMode,
|
||||
ZSTD_compressionParameters cParams)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_initCDict_internal, mode %u", (U32)dictMode);
|
||||
if ((byReference) || (!dictBuffer) || (!dictSize)) {
|
||||
cdict->dictBuffer = NULL;
|
||||
cdict->dictContent = dictBuffer;
|
||||
} else {
|
||||
void* const internalBuffer = ZSTD_malloc(dictSize, cdict->refContext->customMem);
|
||||
cdict->dictBuffer = internalBuffer;
|
||||
cdict->dictContent = internalBuffer;
|
||||
if (!internalBuffer) return ERROR(memory_allocation);
|
||||
memcpy(internalBuffer, dictBuffer, dictSize);
|
||||
}
|
||||
cdict->dictContentSize = dictSize;
|
||||
|
||||
{ ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */,
|
||||
0 /* checksumFlag */, 0 /* noDictIDFlag */ }; /* dummy */
|
||||
ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
|
||||
CHECK_F( ZSTD_compressBegin_internal(cdict->refContext,
|
||||
cdict->dictContent, dictSize, dictMode,
|
||||
NULL,
|
||||
params, ZSTD_CONTENTSIZE_UNKNOWN,
|
||||
ZSTDb_not_buffered) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
|
||||
unsigned byReference, ZSTD_dictMode_e dictMode,
|
||||
ZSTD_compressionParameters cParams, ZSTD_customMem customMem)
|
||||
{
|
||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||
DEBUGLOG(5, "ZSTD_createCDict_advanced, mode %u", (U32)dictMode);
|
||||
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
||||
|
||||
{ ZSTD_CDict* const cdict = (ZSTD_CDict*) ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
|
||||
{ ZSTD_CDict* const cdict = (ZSTD_CDict*)ZSTD_malloc(sizeof(ZSTD_CDict), customMem);
|
||||
ZSTD_CCtx* const cctx = ZSTD_createCCtx_advanced(customMem);
|
||||
|
||||
if (!cdict || !cctx) {
|
||||
@@ -3018,46 +3423,34 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, u
|
||||
ZSTD_freeCCtx(cctx);
|
||||
return NULL;
|
||||
}
|
||||
cdict->refContext = cctx;
|
||||
|
||||
if ((byReference) || (!dictBuffer) || (!dictSize)) {
|
||||
cdict->dictBuffer = NULL;
|
||||
cdict->dictContent = dictBuffer;
|
||||
} else {
|
||||
void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
|
||||
if (!internalBuffer) { ZSTD_free(cctx, customMem); ZSTD_free(cdict, customMem); return NULL; }
|
||||
memcpy(internalBuffer, dictBuffer, dictSize);
|
||||
cdict->dictBuffer = internalBuffer;
|
||||
cdict->dictContent = internalBuffer;
|
||||
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
||||
dictBuffer, dictSize,
|
||||
byReference, dictMode,
|
||||
cParams) )) {
|
||||
ZSTD_freeCDict(cdict);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{ ZSTD_frameParameters const fParams = { 0 /* contentSizeFlag */, 0 /* checksumFlag */, 0 /* noDictIDFlag */ }; /* dummy */
|
||||
ZSTD_parameters const params = ZSTD_makeParams(cParams, fParams);
|
||||
size_t const errorCode = ZSTD_compressBegin_advanced(cctx, cdict->dictContent, dictSize, params, 0);
|
||||
if (ZSTD_isError(errorCode)) {
|
||||
ZSTD_free(cdict->dictBuffer, customMem);
|
||||
ZSTD_free(cdict, customMem);
|
||||
ZSTD_freeCCtx(cctx);
|
||||
return NULL;
|
||||
} }
|
||||
|
||||
cdict->refContext = cctx;
|
||||
cdict->dictContentSize = dictSize;
|
||||
return cdict;
|
||||
}
|
||||
}
|
||||
|
||||
ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
||||
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
||||
return ZSTD_createCDict_advanced(dict, dictSize, 0, cParams, allocator);
|
||||
return ZSTD_createCDict_advanced(dict, dictSize,
|
||||
0 /* byReference */, ZSTD_dm_auto,
|
||||
cParams, ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_customMem const allocator = { NULL, NULL, NULL };
|
||||
ZSTD_compressionParameters cParams = ZSTD_getCParams(compressionLevel, 0, dictSize);
|
||||
return ZSTD_createCDict_advanced(dict, dictSize, 1, cParams, allocator);
|
||||
return ZSTD_createCDict_advanced(dict, dictSize,
|
||||
1 /* byReference */, ZSTD_dm_auto,
|
||||
cParams, ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
||||
@@ -3071,7 +3464,54 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict)
|
||||
}
|
||||
}
|
||||
|
||||
static ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
|
||||
/*! ZSTD_initStaticCDict_advanced() :
|
||||
* Generate a digested dictionary in provided memory area.
|
||||
* workspace: The memory area to emplace the dictionary into.
|
||||
* Provided pointer must 8-bytes aligned.
|
||||
* It must outlive dictionary usage.
|
||||
* workspaceSize: Use ZSTD_estimateCDictSize()
|
||||
* to determine how large workspace must be.
|
||||
* cParams : use ZSTD_getCParams() to transform a compression level
|
||||
* into its relevants cParams.
|
||||
* @return : pointer to ZSTD_CDict*, or NULL if error (size too small)
|
||||
* Note : there is no corresponding "free" function.
|
||||
* Since workspace was allocated externally, it must be freed externally.
|
||||
*/
|
||||
ZSTD_CDict* ZSTD_initStaticCDict(void* workspace, size_t workspaceSize,
|
||||
const void* dict, size_t dictSize,
|
||||
unsigned byReference, ZSTD_dictMode_e dictMode,
|
||||
ZSTD_compressionParameters cParams)
|
||||
{
|
||||
size_t const cctxSize = ZSTD_estimateCCtxSize(cParams);
|
||||
size_t const neededSize = sizeof(ZSTD_CDict) + (byReference ? 0 : dictSize)
|
||||
+ cctxSize;
|
||||
ZSTD_CDict* const cdict = (ZSTD_CDict*) workspace;
|
||||
void* ptr;
|
||||
DEBUGLOG(5, "(size_t)workspace & 7 : %u", (U32)(size_t)workspace & 7);
|
||||
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
||||
DEBUGLOG(5, "(workspaceSize < neededSize) : (%u < %u) => %u",
|
||||
(U32)workspaceSize, (U32)neededSize, (U32)(workspaceSize < neededSize));
|
||||
if (workspaceSize < neededSize) return NULL;
|
||||
|
||||
if (!byReference) {
|
||||
memcpy(cdict+1, dict, dictSize);
|
||||
dict = cdict+1;
|
||||
ptr = (char*)workspace + sizeof(ZSTD_CDict) + dictSize;
|
||||
} else {
|
||||
ptr = cdict+1;
|
||||
}
|
||||
cdict->refContext = ZSTD_initStaticCCtx(ptr, cctxSize);
|
||||
|
||||
if (ZSTD_isError( ZSTD_initCDict_internal(cdict,
|
||||
dict, dictSize,
|
||||
1 /* byReference */, dictMode,
|
||||
cParams) ))
|
||||
return NULL;
|
||||
|
||||
return cdict;
|
||||
}
|
||||
|
||||
ZSTD_parameters ZSTD_getParamsFromCDict(const ZSTD_CDict* cdict) {
|
||||
return ZSTD_getParamsFromCCtx(cdict->refContext);
|
||||
}
|
||||
|
||||
@@ -3081,16 +3521,16 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
||||
ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,
|
||||
ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)
|
||||
{
|
||||
if (cdict==NULL) return ERROR(GENERIC); /* does not support NULL cdict */
|
||||
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced : dictIDFlag == %u \n", !fParams.noDictIDFlag);
|
||||
if (cdict->dictContentSize)
|
||||
CHECK_F( ZSTD_copyCCtx_internal(cctx, cdict->refContext, fParams, pledgedSrcSize) )
|
||||
else {
|
||||
ZSTD_parameters params = cdict->refContext->params;
|
||||
if (cdict==NULL) return ERROR(dictionary_wrong);
|
||||
{ ZSTD_parameters params = cdict->refContext->appliedParams;
|
||||
params.fParams = fParams;
|
||||
CHECK_F(ZSTD_compressBegin_internal(cctx, NULL, 0, params, pledgedSrcSize));
|
||||
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict_advanced");
|
||||
return ZSTD_compressBegin_internal(cctx,
|
||||
NULL, 0, ZSTD_dm_auto,
|
||||
cdict,
|
||||
params, pledgedSrcSize,
|
||||
ZSTDb_not_buffered);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ZSTD_compressBegin_usingCDict() :
|
||||
@@ -3099,7 +3539,7 @@ size_t ZSTD_compressBegin_usingCDict_advanced(
|
||||
size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)
|
||||
{
|
||||
ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };
|
||||
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u \n", !fParams.noDictIDFlag);
|
||||
DEBUGLOG(5, "ZSTD_compressBegin_usingCDict : dictIDFlag == %u", !fParams.noDictIDFlag);
|
||||
return ZSTD_compressBegin_usingCDict_advanced(cctx, cdict, fParams, 0);
|
||||
}
|
||||
|
||||
@@ -3134,12 +3574,11 @@ size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
|
||||
ZSTD_CStream* ZSTD_createCStream(void)
|
||||
{
|
||||
return ZSTD_createCStream_advanced(defaultCustomMem);
|
||||
return ZSTD_createCStream_advanced(ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)
|
||||
{
|
||||
/* CStream and CCtx are now same object */
|
||||
{ /* CStream and CCtx are now same object */
|
||||
return ZSTD_createCCtx_advanced(customMem);
|
||||
}
|
||||
|
||||
@@ -3148,35 +3587,28 @@ size_t ZSTD_freeCStream(ZSTD_CStream* zcs)
|
||||
return ZSTD_freeCCtx(zcs); /* same object */
|
||||
}
|
||||
|
||||
size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams)
|
||||
{
|
||||
size_t const CCtxSize = ZSTD_estimateCCtxSize(cParams);
|
||||
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << cParams.windowLog);
|
||||
size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize;
|
||||
size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1;
|
||||
size_t const streamingSize = inBuffSize + outBuffSize;
|
||||
|
||||
return CCtxSize + streamingSize;
|
||||
}
|
||||
|
||||
|
||||
/*====== Initialization ======*/
|
||||
|
||||
size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
|
||||
size_t ZSTD_CStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX; }
|
||||
|
||||
size_t ZSTD_CStreamOutSize(void)
|
||||
{
|
||||
return ZSTD_compressBound(ZSTD_BLOCKSIZE_ABSOLUTEMAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
|
||||
return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;
|
||||
}
|
||||
|
||||
static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs,
|
||||
ZSTD_parameters params,
|
||||
unsigned long long pledgedSrcSize)
|
||||
{
|
||||
if (zcs->inBuffSize==0) return ERROR(stage_wrong); /* zcs has not been init at least once => can't reset */
|
||||
DEBUGLOG(5, "ZSTD_resetCStream_internal");
|
||||
|
||||
DEBUGLOG(5, "ZSTD_resetCStream_internal : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
|
||||
|
||||
if (zcs->cdict) CHECK_F(ZSTD_compressBegin_usingCDict_advanced(zcs, zcs->cdict, params.fParams, pledgedSrcSize))
|
||||
else CHECK_F(ZSTD_compressBegin_internal(zcs, NULL, 0, params, pledgedSrcSize));
|
||||
CHECK_F( ZSTD_compressBegin_internal(zcs,
|
||||
NULL, 0, ZSTD_dm_auto,
|
||||
zcs->cdict,
|
||||
params, pledgedSrcSize,
|
||||
ZSTDb_buffered) );
|
||||
|
||||
zcs->inToCompress = 0;
|
||||
zcs->inBuffPos = 0;
|
||||
@@ -3184,87 +3616,79 @@ static size_t ZSTD_resetCStream_internal(ZSTD_CStream* zcs, ZSTD_parameters para
|
||||
zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
|
||||
zcs->streamStage = zcss_load;
|
||||
zcs->frameEnded = 0;
|
||||
zcs->pledgedSrcSize = pledgedSrcSize;
|
||||
return 0; /* ready to go */
|
||||
}
|
||||
|
||||
size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
|
||||
ZSTD_parameters params = zcs->params;
|
||||
ZSTD_parameters params = zcs->requestedParams;
|
||||
params.fParams.contentSizeFlag = (pledgedSrcSize > 0);
|
||||
DEBUGLOG(5, "ZSTD_resetCStream : dictIDFlag == %u \n", !zcs->params.fParams.noDictIDFlag);
|
||||
DEBUGLOG(5, "ZSTD_resetCStream");
|
||||
if (zcs->compressionLevel != ZSTD_CLEVEL_CUSTOM) {
|
||||
params.cParams = ZSTD_getCParams(zcs->compressionLevel, pledgedSrcSize, 0 /* dictSize */);
|
||||
}
|
||||
return ZSTD_resetCStream_internal(zcs, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
/* ZSTD_initCStream_internal() :
|
||||
* params are supposed validated at this stage
|
||||
* and zcs->cdict is supposed to be correct */
|
||||
static size_t ZSTD_initCStream_stage2(ZSTD_CStream* zcs,
|
||||
const ZSTD_parameters params,
|
||||
unsigned long long pledgedSrcSize)
|
||||
/*! ZSTD_initCStream_internal() :
|
||||
* Assumption 1 : params are valid
|
||||
* Assumption 2 : either dict, or cdict, is defined, not both */
|
||||
size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
||||
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
DEBUGLOG(5, "ZSTD_initCStream_internal");
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
zcs->blockSize = MIN(ZSTD_BLOCKSIZE_ABSOLUTEMAX, (size_t)1 << params.cParams.windowLog);
|
||||
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
||||
|
||||
/* allocate buffers */
|
||||
{ size_t const neededInBuffSize = ((size_t)1 << params.cParams.windowLog) + zcs->blockSize;
|
||||
if (zcs->inBuffSize < neededInBuffSize) {
|
||||
zcs->inBuffSize = 0;
|
||||
ZSTD_free(zcs->inBuff, zcs->customMem);
|
||||
zcs->inBuff = (char*)ZSTD_malloc(neededInBuffSize, zcs->customMem);
|
||||
if (zcs->inBuff == NULL) return ERROR(memory_allocation);
|
||||
zcs->inBuffSize = neededInBuffSize;
|
||||
if (dict && dictSize >= 8) {
|
||||
DEBUGLOG(5, "loading dictionary of size %u", (U32)dictSize);
|
||||
if (zcs->staticSize) { /* static CCtx : never uses malloc */
|
||||
/* incompatible with internal cdict creation */
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
}
|
||||
if (zcs->outBuffSize < ZSTD_compressBound(zcs->blockSize)+1) {
|
||||
size_t const outBuffSize = ZSTD_compressBound(zcs->blockSize)+1;
|
||||
zcs->outBuffSize = 0;
|
||||
ZSTD_free(zcs->outBuff, zcs->customMem);
|
||||
zcs->outBuff = (char*)ZSTD_malloc(outBuffSize, zcs->customMem);
|
||||
if (zcs->outBuff == NULL) return ERROR(memory_allocation);
|
||||
zcs->outBuffSize = outBuffSize;
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
||||
0 /* byReference */, ZSTD_dm_auto,
|
||||
params.cParams, zcs->customMem);
|
||||
zcs->cdict = zcs->cdictLocal;
|
||||
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
||||
} else {
|
||||
if (cdict) {
|
||||
ZSTD_parameters const cdictParams = ZSTD_getParamsFromCDict(cdict);
|
||||
params.cParams = cdictParams.cParams; /* cParams are enforced from cdict */
|
||||
}
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = NULL;
|
||||
zcs->cdict = cdict;
|
||||
}
|
||||
|
||||
DEBUGLOG(5, "ZSTD_initCStream_stage2 : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
|
||||
zcs->requestedParams = params;
|
||||
zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
||||
return ZSTD_resetCStream_internal(zcs, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
/* ZSTD_initCStream_usingCDict_advanced() :
|
||||
* same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
|
||||
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams)
|
||||
{
|
||||
if (!cdict) return ERROR(GENERIC); /* cannot handle NULL cdict (does not know what to do) */
|
||||
size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_frameParameters fParams,
|
||||
unsigned long long pledgedSrcSize)
|
||||
{ /* cannot handle NULL cdict (does not know what to do) */
|
||||
if (!cdict) return ERROR(dictionary_wrong);
|
||||
{ ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
|
||||
params.fParams = fParams;
|
||||
zcs->cdict = cdict;
|
||||
return ZSTD_initCStream_stage2(zcs, params, pledgedSrcSize);
|
||||
return ZSTD_initCStream_internal(zcs,
|
||||
NULL, 0, cdict,
|
||||
params, pledgedSrcSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* note : cdict must outlive compression session */
|
||||
size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)
|
||||
{
|
||||
ZSTD_frameParameters const fParams = { 0 /* content */, 0 /* checksum */, 0 /* noDictID */ };
|
||||
return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, 0, fParams);
|
||||
}
|
||||
|
||||
static size_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
zcs->cdict = NULL;
|
||||
|
||||
if (dict && dictSize >= 8) {
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize, 0 /* copy */, params.cParams, zcs->customMem);
|
||||
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
||||
zcs->cdict = zcs->cdictLocal;
|
||||
}
|
||||
|
||||
DEBUGLOG(5, "ZSTD_initCStream_internal : dictIDFlag == %u \n", !params.fParams.noDictIDFlag);
|
||||
return ZSTD_initCStream_stage2(zcs, params, pledgedSrcSize);
|
||||
ZSTD_frameParameters const fParams = { 0 /* contentSize */, 0 /* checksum */, 0 /* hideDictID */ };
|
||||
return ZSTD_initCStream_usingCDict_advanced(zcs, cdict, fParams, 0); /* note : will check that cdict != NULL */
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
||||
@@ -3272,127 +3696,161 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
CHECK_F( ZSTD_checkCParams(params.cParams) );
|
||||
DEBUGLOG(5, "ZSTD_initCStream_advanced : pledgedSrcSize == %u \n", (U32)pledgedSrcSize);
|
||||
DEBUGLOG(5, "wlog %u \n", params.cParams.windowLog);
|
||||
return ZSTD_initCStream_internal(zcs, dict, dictSize, params, pledgedSrcSize);
|
||||
zcs->requestedParams = params;
|
||||
zcs->compressionLevel = ZSTD_CLEVEL_CUSTOM;
|
||||
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, dictSize);
|
||||
return ZSTD_initCStream_internal(zcs, dict, dictSize, params, 0);
|
||||
zcs->compressionLevel = compressionLevel;
|
||||
return ZSTD_initCStream_internal(zcs, dict, dictSize, NULL, params, 0);
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
ZSTD_parameters params = ZSTD_getParams(compressionLevel, pledgedSrcSize, 0);
|
||||
params.fParams.contentSizeFlag = (pledgedSrcSize>0);
|
||||
return ZSTD_initCStream_internal(zcs, NULL, 0, params, pledgedSrcSize);
|
||||
return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)
|
||||
{
|
||||
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
|
||||
return ZSTD_initCStream_internal(zcs, NULL, 0, params, 0);
|
||||
}
|
||||
|
||||
size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)
|
||||
{
|
||||
return ZSTD_sizeof_CCtx(zcs); /* same object */
|
||||
return ZSTD_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
|
||||
}
|
||||
|
||||
/*====== Compression ======*/
|
||||
|
||||
typedef enum { zsf_gather, zsf_flush, zsf_end } ZSTD_flush_e;
|
||||
|
||||
MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize)
|
||||
{
|
||||
size_t const length = MIN(dstCapacity, srcSize);
|
||||
memcpy(dst, src, length);
|
||||
if (length) memcpy(dst, src, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
void* dst, size_t* dstCapacityPtr,
|
||||
const void* src, size_t* srcSizePtr,
|
||||
ZSTD_flush_e const flush)
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective const flushMode)
|
||||
{
|
||||
const char* const istart = (const char*)input->src;
|
||||
const char* const iend = istart + input->size;
|
||||
const char* ip = istart + input->pos;
|
||||
char* const ostart = (char*)output->dst;
|
||||
char* const oend = ostart + output->size;
|
||||
char* op = ostart + output->pos;
|
||||
U32 someMoreWork = 1;
|
||||
const char* const istart = (const char*)src;
|
||||
const char* const iend = istart + *srcSizePtr;
|
||||
const char* ip = istart;
|
||||
char* const ostart = (char*)dst;
|
||||
char* const oend = ostart + *dstCapacityPtr;
|
||||
char* op = ostart;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_compressStream_generic \n");
|
||||
/* check expectations */
|
||||
DEBUGLOG(5, "ZSTD_compressStream_generic");
|
||||
assert(zcs->inBuff != NULL);
|
||||
assert(zcs->inBuffSize>0);
|
||||
assert(zcs->outBuff!= NULL);
|
||||
assert(zcs->outBuffSize>0);
|
||||
assert(output->pos <= output->size);
|
||||
assert(input->pos <= input->size);
|
||||
|
||||
while (someMoreWork) {
|
||||
switch(zcs->streamStage)
|
||||
{
|
||||
case zcss_init: return ERROR(init_missing); /* call ZBUFF_compressInit() first ! */
|
||||
case zcss_init:
|
||||
/* call ZSTD_initCStream() first ! */
|
||||
return ERROR(init_missing);
|
||||
|
||||
case zcss_load:
|
||||
/* complete inBuffer */
|
||||
{ size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;
|
||||
size_t const loaded = ZSTD_limitCopy(zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend-ip);
|
||||
DEBUGLOG(5, "loading %u/%u \n", (U32)loaded, (U32)toLoad);
|
||||
size_t const loaded = ZSTD_limitCopy(
|
||||
zcs->inBuff + zcs->inBuffPos, toLoad,
|
||||
ip, iend-ip);
|
||||
zcs->inBuffPos += loaded;
|
||||
ip += loaded;
|
||||
if ( (zcs->inBuffPos==zcs->inToCompress) || (!flush && (toLoad != loaded)) ) {
|
||||
someMoreWork = 0; break; /* not enough input to get a full block : stop there, wait for more */
|
||||
} }
|
||||
if ( (flushMode == ZSTD_e_continue)
|
||||
&& (zcs->inBuffPos < zcs->inBuffTarget) ) {
|
||||
/* not enough input to fill full block : stop here */
|
||||
someMoreWork = 0; break;
|
||||
}
|
||||
if ( (flushMode == ZSTD_e_flush)
|
||||
&& (zcs->inBuffPos == zcs->inToCompress) ) {
|
||||
/* empty */
|
||||
someMoreWork = 0; break;
|
||||
}
|
||||
}
|
||||
/* compress current block (note : this stage cannot be stopped in the middle) */
|
||||
DEBUGLOG(5, "stream compression stage (flush==%u)\n", flush);
|
||||
DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode);
|
||||
{ void* cDst;
|
||||
size_t cSize;
|
||||
size_t const iSize = zcs->inBuffPos - zcs->inToCompress;
|
||||
size_t oSize = oend-op;
|
||||
unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);
|
||||
if (oSize >= ZSTD_compressBound(iSize))
|
||||
cDst = op; /* compress directly into output buffer (avoid flush stage) */
|
||||
cDst = op; /* compress into output buffer, to skip flush stage */
|
||||
else
|
||||
cDst = zcs->outBuff, oSize = zcs->outBuffSize;
|
||||
cSize = (flush == zsf_end) ?
|
||||
ZSTD_compressEnd(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize) :
|
||||
ZSTD_compressContinue(zcs, cDst, oSize, zcs->inBuff + zcs->inToCompress, iSize);
|
||||
cSize = lastBlock ?
|
||||
ZSTD_compressEnd(zcs, cDst, oSize,
|
||||
zcs->inBuff + zcs->inToCompress, iSize) :
|
||||
ZSTD_compressContinue(zcs, cDst, oSize,
|
||||
zcs->inBuff + zcs->inToCompress, iSize);
|
||||
if (ZSTD_isError(cSize)) return cSize;
|
||||
DEBUGLOG(5, "cSize = %u \n", (U32)cSize);
|
||||
if (flush == zsf_end) zcs->frameEnded = 1;
|
||||
zcs->frameEnded = lastBlock;
|
||||
/* prepare next block */
|
||||
zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize;
|
||||
if (zcs->inBuffTarget > zcs->inBuffSize)
|
||||
zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; /* note : inBuffTarget == blockSize <= inBuffSize */
|
||||
assert(zcs->inBuffTarget <= zcs->inBuffSize);
|
||||
zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize;
|
||||
DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u",
|
||||
(U32)zcs->inBuffTarget, (U32)zcs->inBuffSize);
|
||||
if (!lastBlock)
|
||||
assert(zcs->inBuffTarget <= zcs->inBuffSize);
|
||||
zcs->inToCompress = zcs->inBuffPos;
|
||||
if (cDst == op) { op += cSize; break; } /* no need to flush */
|
||||
if (cDst == op) { /* no need to flush */
|
||||
op += cSize;
|
||||
if (zcs->frameEnded) {
|
||||
DEBUGLOG(5, "Frame completed directly in outBuffer");
|
||||
someMoreWork = 0;
|
||||
ZSTD_startNewCompression(zcs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
zcs->outBuffContentSize = cSize;
|
||||
zcs->outBuffFlushedSize = 0;
|
||||
zcs->streamStage = zcss_flush; /* pass-through to flush stage */
|
||||
zcs->streamStage = zcss_flush; /* pass-through to flush stage */
|
||||
}
|
||||
/* fall-through */
|
||||
case zcss_flush:
|
||||
DEBUGLOG(5, "flush stage \n");
|
||||
DEBUGLOG(5, "flush stage");
|
||||
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
||||
size_t const flushed = ZSTD_limitCopy(op, oend-op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
||||
DEBUGLOG(5, "toFlush: %u ; flushed: %u \n", (U32)toFlush, (U32)flushed);
|
||||
size_t const flushed = ZSTD_limitCopy(op, oend-op,
|
||||
zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
||||
DEBUGLOG(5, "toFlush: %u ; flushed: %u", (U32)toFlush, (U32)flushed);
|
||||
op += flushed;
|
||||
zcs->outBuffFlushedSize += flushed;
|
||||
if (toFlush!=flushed) { someMoreWork = 0; break; } /* dst too small to store flushed data : stop there */
|
||||
if (toFlush!=flushed) {
|
||||
/* dst too small to store flushed data : stop there */
|
||||
someMoreWork = 0;
|
||||
break;
|
||||
}
|
||||
zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;
|
||||
if (zcs->frameEnded) {
|
||||
DEBUGLOG(5, "Frame completed on flush");
|
||||
someMoreWork = 0;
|
||||
ZSTD_startNewCompression(zcs);
|
||||
break;
|
||||
}
|
||||
zcs->streamStage = zcss_load;
|
||||
break;
|
||||
}
|
||||
|
||||
case zcss_final:
|
||||
someMoreWork = 0; /* do nothing */
|
||||
break;
|
||||
|
||||
default:
|
||||
return ERROR(GENERIC); /* impossible */
|
||||
default: /* impossible */
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
*srcSizePtr = ip - istart;
|
||||
*dstCapacityPtr = op - ostart;
|
||||
input->pos = ip - istart;
|
||||
output->pos = op - ostart;
|
||||
if (zcs->frameEnded) return 0;
|
||||
{ size_t hintInSize = zcs->inBuffTarget - zcs->inBuffPos;
|
||||
if (hintInSize==0) hintInSize = zcs->blockSize;
|
||||
@@ -3402,14 +3860,82 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
|
||||
|
||||
size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||
{
|
||||
size_t sizeRead = input->size - input->pos;
|
||||
size_t sizeWritten = output->size - output->pos;
|
||||
size_t const result = ZSTD_compressStream_generic(zcs,
|
||||
(char*)(output->dst) + output->pos, &sizeWritten,
|
||||
(const char*)(input->src) + input->pos, &sizeRead, zsf_gather);
|
||||
input->pos += sizeRead;
|
||||
output->pos += sizeWritten;
|
||||
return result;
|
||||
/* check conditions */
|
||||
if (output->pos > output->size) return ERROR(GENERIC);
|
||||
if (input->pos > input->size) return ERROR(GENERIC);
|
||||
|
||||
return ZSTD_compressStream_generic(zcs, output, input, ZSTD_e_continue);
|
||||
}
|
||||
|
||||
/*! ZSTDMT_initCStream_internal() :
|
||||
* Private use only. Init streaming operation.
|
||||
* expects params to be valid.
|
||||
* must receive dict, or cdict, or none, but not both.
|
||||
* @return : 0, or an error code */
|
||||
size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
||||
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize);
|
||||
|
||||
|
||||
size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp)
|
||||
{
|
||||
/* check conditions */
|
||||
if (output->pos > output->size) return ERROR(GENERIC);
|
||||
if (input->pos > input->size) return ERROR(GENERIC);
|
||||
assert(cctx!=NULL);
|
||||
|
||||
if (cctx->streamStage == zcss_init) {
|
||||
/* transparent reset */
|
||||
ZSTD_parameters params = cctx->requestedParams;
|
||||
if (cctx->compressionLevel != ZSTD_CLEVEL_CUSTOM)
|
||||
params.cParams = ZSTD_getCParams(cctx->compressionLevel,
|
||||
cctx->pledgedSrcSizePlusOne-1, 0 /* dictSize */);
|
||||
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
if (cctx->nbThreads > 1) {
|
||||
DEBUGLOG(4, "call ZSTDMT_initCStream_internal");
|
||||
CHECK_F( ZSTDMT_initCStream_internal(cctx->mtctx, NULL, 0, cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) );
|
||||
cctx->streamStage = zcss_load;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
CHECK_F( ZSTD_resetCStream_internal(cctx, params, cctx->pledgedSrcSizePlusOne-1) );
|
||||
} }
|
||||
|
||||
#ifdef ZSTD_MULTITHREAD
|
||||
if (cctx->nbThreads > 1) {
|
||||
size_t const flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);
|
||||
DEBUGLOG(4, "ZSTDMT_compressStream_generic : %u", (U32)flushMin);
|
||||
if ( ZSTD_isError(flushMin)
|
||||
|| (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */
|
||||
ZSTD_startNewCompression(cctx);
|
||||
}
|
||||
return flushMin;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUGLOG(5, "calling ZSTD_compressStream_generic(%i,...)", endOp);
|
||||
CHECK_F( ZSTD_compressStream_generic(cctx, output, input, endOp) );
|
||||
DEBUGLOG(5, "completed ZSTD_compress_generic");
|
||||
return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */
|
||||
}
|
||||
|
||||
size_t ZSTD_compress_generic_simpleArgs (
|
||||
ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity, size_t* dstPos,
|
||||
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_compress_generic() will check validity of dstPos and srcPos */
|
||||
size_t const cErr = ZSTD_compress_generic(cctx, &output, &input, endOp);
|
||||
*dstPos = output.pos;
|
||||
*srcPos = input.pos;
|
||||
return cErr;
|
||||
}
|
||||
|
||||
|
||||
@@ -3419,62 +3945,27 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf
|
||||
* @return : amount of data remaining to flush */
|
||||
size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
||||
{
|
||||
size_t srcSize = 0;
|
||||
size_t sizeWritten = output->size - output->pos;
|
||||
size_t const result = ZSTD_compressStream_generic(zcs,
|
||||
(char*)(output->dst) + output->pos, &sizeWritten,
|
||||
&srcSize, &srcSize, /* use a valid src address instead of NULL */
|
||||
zsf_flush);
|
||||
output->pos += sizeWritten;
|
||||
if (ZSTD_isError(result)) return result;
|
||||
return zcs->outBuffContentSize - zcs->outBuffFlushedSize; /* remaining to flush */
|
||||
ZSTD_inBuffer input = { NULL, 0, 0 };
|
||||
if (output->pos > output->size) return ERROR(GENERIC);
|
||||
CHECK_F( ZSTD_compressStream_generic(zcs, output, &input, ZSTD_e_flush) );
|
||||
return zcs->outBuffContentSize - zcs->outBuffFlushedSize; /* remaining to flush */
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
|
||||
{
|
||||
BYTE* const ostart = (BYTE*)(output->dst) + output->pos;
|
||||
BYTE* const oend = (BYTE*)(output->dst) + output->size;
|
||||
BYTE* op = ostart;
|
||||
ZSTD_inBuffer input = { NULL, 0, 0 };
|
||||
if (output->pos > output->size) return ERROR(GENERIC);
|
||||
CHECK_F( ZSTD_compressStream_generic(zcs, output, &input, ZSTD_e_end) );
|
||||
|
||||
DEBUGLOG(5, "ZSTD_endStream (dstCapacity : %u) \n", (U32)(oend-op));
|
||||
if (zcs->streamStage != zcss_final) {
|
||||
/* flush whatever remains */
|
||||
size_t srcSize = 0;
|
||||
size_t sizeWritten = output->size - output->pos;
|
||||
size_t const notEnded = ZSTD_compressStream_generic(zcs, ostart, &sizeWritten,
|
||||
&srcSize /* use a valid src address instead of NULL */, &srcSize, zsf_end);
|
||||
size_t const remainingToFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
||||
op += sizeWritten;
|
||||
if (remainingToFlush) {
|
||||
output->pos += sizeWritten;
|
||||
return remainingToFlush + ZSTD_BLOCKHEADERSIZE /* final empty block */
|
||||
+ ((zcs->params.fParams.checksumFlag > 0) * 4) /* optional 32-bits checksum */;
|
||||
}
|
||||
/* create epilogue */
|
||||
zcs->streamStage = zcss_final;
|
||||
zcs->outBuffContentSize = !notEnded ? 0 :
|
||||
/* write epilogue, including final empty block, into outBuff */
|
||||
ZSTD_compressEnd(zcs, zcs->outBuff, zcs->outBuffSize, NULL, 0);
|
||||
if (ZSTD_isError(zcs->outBuffContentSize)) return zcs->outBuffContentSize;
|
||||
}
|
||||
|
||||
/* flush epilogue */
|
||||
{ size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
||||
size_t const flushed = ZSTD_limitCopy(op, oend-op, zcs->outBuff + zcs->outBuffFlushedSize, toFlush);
|
||||
op += flushed;
|
||||
zcs->outBuffFlushedSize += flushed;
|
||||
output->pos += op-ostart;
|
||||
if (toFlush==flushed) zcs->streamStage = zcss_init; /* end reached */
|
||||
return toFlush - flushed;
|
||||
}
|
||||
DEBUGLOG(5, "ZSTD_endStream : remaining to flush : %u",
|
||||
(unsigned)(zcs->outBuffContentSize - zcs->outBuffFlushedSize));
|
||||
return zcs->outBuffContentSize - zcs->outBuffFlushedSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-===== Pre-defined compression levels =====-*/
|
||||
|
||||
#define ZSTD_DEFAULT_CLEVEL 1
|
||||
#define ZSTD_MAX_CLEVEL 22
|
||||
int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
|
||||
|
||||
@@ -3588,30 +4079,23 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV
|
||||
/*! ZSTD_getCParams() :
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level, `srcSize` and `dictSize`.
|
||||
* Size values are optional, provide 0 if not known or unused */
|
||||
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSize, size_t dictSize)
|
||||
ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)
|
||||
{
|
||||
ZSTD_compressionParameters cp;
|
||||
size_t const addedSize = srcSize ? 0 : 500;
|
||||
U64 const rSize = srcSize+dictSize ? srcSize+dictSize+addedSize : (U64)-1;
|
||||
size_t const addedSize = srcSizeHint ? 0 : 500;
|
||||
U64 const rSize = srcSizeHint+dictSize ? srcSizeHint+dictSize+addedSize : (U64)-1;
|
||||
U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); /* intentional underflow for srcSizeHint == 0 */
|
||||
if (compressionLevel <= 0) compressionLevel = ZSTD_DEFAULT_CLEVEL; /* 0 == default; no negative compressionLevel yet */
|
||||
if (compressionLevel <= 0) compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default; no negative compressionLevel yet */
|
||||
if (compressionLevel > ZSTD_MAX_CLEVEL) compressionLevel = ZSTD_MAX_CLEVEL;
|
||||
cp = ZSTD_defaultCParameters[tableID][compressionLevel];
|
||||
if (MEM_32bits()) { /* auto-correction, for 32-bits mode */
|
||||
if (cp.windowLog > ZSTD_WINDOWLOG_MAX) cp.windowLog = ZSTD_WINDOWLOG_MAX;
|
||||
if (cp.chainLog > ZSTD_CHAINLOG_MAX) cp.chainLog = ZSTD_CHAINLOG_MAX;
|
||||
if (cp.hashLog > ZSTD_HASHLOG_MAX) cp.hashLog = ZSTD_HASHLOG_MAX;
|
||||
}
|
||||
cp = ZSTD_adjustCParams(cp, srcSize, dictSize);
|
||||
return cp;
|
||||
{ ZSTD_compressionParameters const cp = ZSTD_defaultCParameters[tableID][compressionLevel];
|
||||
return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); }
|
||||
}
|
||||
|
||||
/*! ZSTD_getParams() :
|
||||
* same as ZSTD_getCParams(), but @return a `ZSTD_parameters` object (instead of `ZSTD_compressionParameters`).
|
||||
* All fields of `ZSTD_frameParameters` are set to default (0) */
|
||||
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSize, size_t dictSize) {
|
||||
ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) {
|
||||
ZSTD_parameters params;
|
||||
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSize, dictSize);
|
||||
ZSTD_compressionParameters const cParams = ZSTD_getCParams(compressionLevel, srcSizeHint, dictSize);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.cParams = cParams;
|
||||
return params;
|
||||
|
||||
+30
-15
@@ -43,6 +43,7 @@ MEM_STATIC void ZSTD_rescaleFreqs(seqStore_t* ssPtr, const BYTE* src, size_t src
|
||||
if (ssPtr->litLengthSum == 0) {
|
||||
if (srcSize <= 1024) ssPtr->staticPrices = 1;
|
||||
|
||||
assert(ssPtr->litFreq!=NULL);
|
||||
for (u=0; u<=MaxLit; u++)
|
||||
ssPtr->litFreq[u] = 0;
|
||||
for (u=0; u<srcSize; u++)
|
||||
@@ -201,6 +202,20 @@ MEM_STATIC void ZSTD_updatePrice(seqStore_t* seqStorePtr, U32 litLength, const B
|
||||
}
|
||||
|
||||
|
||||
/* function safe only for comparisons */
|
||||
MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
default :
|
||||
case 4 : return MEM_read32(memPtr);
|
||||
case 3 : if (MEM_isLittleEndian())
|
||||
return MEM_read32(memPtr)<<8;
|
||||
else
|
||||
return MEM_read32(memPtr)>>8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Update hashTable3 up to ip (excluded)
|
||||
Assumption : always within prefix (i.e. not within extDict) */
|
||||
@@ -234,12 +249,12 @@ static U32 ZSTD_insertBtAndGetAllMatches (
|
||||
{
|
||||
const BYTE* const base = zc->base;
|
||||
const U32 current = (U32)(ip-base);
|
||||
const U32 hashLog = zc->params.cParams.hashLog;
|
||||
const U32 hashLog = zc->appliedParams.cParams.hashLog;
|
||||
const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
|
||||
U32* const hashTable = zc->hashTable;
|
||||
U32 matchIndex = hashTable[h];
|
||||
U32* const bt = zc->chainTable;
|
||||
const U32 btLog = zc->params.cParams.chainLog - 1;
|
||||
const U32 btLog = zc->appliedParams.cParams.chainLog - 1;
|
||||
const U32 btMask= (1U << btLog) - 1;
|
||||
size_t commonLengthSmaller=0, commonLengthLarger=0;
|
||||
const BYTE* const dictBase = zc->dictBase;
|
||||
@@ -267,7 +282,7 @@ static U32 ZSTD_insertBtAndGetAllMatches (
|
||||
if (match[bestLength] == ip[bestLength]) currentMl = ZSTD_count(ip, match, iLimit);
|
||||
} else {
|
||||
match = dictBase + matchIndex3;
|
||||
if (MEM_readMINMATCH(match, MINMATCH) == MEM_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
|
||||
if (ZSTD_readMINMATCH(match, MINMATCH) == ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
|
||||
currentMl = ZSTD_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
|
||||
}
|
||||
|
||||
@@ -410,10 +425,10 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const base = ctx->base;
|
||||
const BYTE* const prefixStart = base + ctx->dictLimit;
|
||||
|
||||
const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
|
||||
const U32 sufficient_len = ctx->params.cParams.targetLength;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
|
||||
const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
|
||||
const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
|
||||
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
||||
const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
|
||||
|
||||
ZSTD_optimal_t* opt = seqStorePtr->priceTable;
|
||||
ZSTD_match_t* matches = seqStorePtr->matchTable;
|
||||
@@ -439,7 +454,7 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
|
||||
for (i=(ip == anchor); i<last_i; i++) {
|
||||
const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
|
||||
if ( (repCur > 0) && (repCur < (S32)(ip-prefixStart))
|
||||
&& (MEM_readMINMATCH(ip, minMatch) == MEM_readMINMATCH(ip - repCur, minMatch))) {
|
||||
&& (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
|
||||
mlen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repCur, iend) + minMatch;
|
||||
if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
|
||||
best_mlen = mlen; best_off = i; cur = 0; last_pos = 1;
|
||||
@@ -524,7 +539,7 @@ void ZSTD_compressBlock_opt_generic(ZSTD_CCtx* ctx,
|
||||
for (i=(opt[cur].mlen != 1); i<last_i; i++) { /* check rep */
|
||||
const S32 repCur = (i==ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
|
||||
if ( (repCur > 0) && (repCur < (S32)(inr-prefixStart))
|
||||
&& (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(inr - repCur, minMatch))) {
|
||||
&& (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
|
||||
mlen = (U32)ZSTD_count(inr+minMatch, inr+minMatch - repCur, iend) + minMatch;
|
||||
|
||||
if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
|
||||
@@ -663,10 +678,10 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const dictBase = ctx->dictBase;
|
||||
const BYTE* const dictEnd = dictBase + dictLimit;
|
||||
|
||||
const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
|
||||
const U32 sufficient_len = ctx->params.cParams.targetLength;
|
||||
const U32 mls = ctx->params.cParams.searchLength;
|
||||
const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
|
||||
const U32 maxSearches = 1U << ctx->appliedParams.cParams.searchLog;
|
||||
const U32 sufficient_len = ctx->appliedParams.cParams.targetLength;
|
||||
const U32 mls = ctx->appliedParams.cParams.searchLength;
|
||||
const U32 minMatch = (ctx->appliedParams.cParams.searchLength == 3) ? 3 : 4;
|
||||
|
||||
ZSTD_optimal_t* opt = seqStorePtr->priceTable;
|
||||
ZSTD_match_t* matches = seqStorePtr->matchTable;
|
||||
@@ -698,7 +713,7 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const repMatch = repBase + repIndex;
|
||||
if ( (repCur > 0 && repCur <= (S32)current)
|
||||
&& (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
|
||||
&& (MEM_readMINMATCH(ip, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) {
|
||||
&& (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
|
||||
/* repcode detected we should take it */
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
mlen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
|
||||
@@ -794,7 +809,7 @@ void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx* ctx,
|
||||
const BYTE* const repMatch = repBase + repIndex;
|
||||
if ( (repCur > 0 && repCur <= (S32)(current+cur))
|
||||
&& (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex>lowestIndex)) /* intentional overflow */
|
||||
&& (MEM_readMINMATCH(inr, minMatch) == MEM_readMINMATCH(repMatch, minMatch)) ) {
|
||||
&& (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {
|
||||
/* repcode detected */
|
||||
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
|
||||
mlen = (U32)ZSTD_count_2segments(inr+minMatch, repMatch+minMatch, iend, repEnd, prefixStart) + minMatch;
|
||||
|
||||
+270
-129
@@ -14,34 +14,31 @@
|
||||
|
||||
/* ====== Compiler specifics ====== */
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||
# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */
|
||||
#endif
|
||||
|
||||
|
||||
/* ====== Dependencies ====== */
|
||||
#include <stdlib.h> /* malloc */
|
||||
#include <string.h> /* memcpy */
|
||||
#include "pool.h" /* threadpool */
|
||||
#include "threading.h" /* mutex */
|
||||
#include "zstd_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
||||
#include <string.h> /* memcpy, memset */
|
||||
#include "pool.h" /* threadpool */
|
||||
#include "threading.h" /* mutex */
|
||||
#include "zstd_internal.h" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */
|
||||
#include "zstdmt_compress.h"
|
||||
|
||||
|
||||
/* ====== Debug ====== */
|
||||
#if 0
|
||||
#if defined(ZSTD_DEBUG) && (ZSTD_DEBUG>=2)
|
||||
|
||||
# include <stdio.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/times.h>
|
||||
static unsigned g_debugLevel = 5;
|
||||
# define DEBUGLOGRAW(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __VA_ARGS__); }
|
||||
# define DEBUGLOG(l, ...) if (l<=g_debugLevel) { fprintf(stderr, __FILE__ ": "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, " \n"); }
|
||||
# define DEBUGLOGRAW(l, ...) if (l<=ZSTD_DEBUG) { fprintf(stderr, __VA_ARGS__); }
|
||||
|
||||
# define DEBUG_PRINTHEX(l,p,n) { \
|
||||
unsigned debug_u; \
|
||||
for (debug_u=0; debug_u<(n); debug_u++) \
|
||||
# define DEBUG_PRINTHEX(l,p,n) { \
|
||||
unsigned debug_u; \
|
||||
for (debug_u=0; debug_u<(n); debug_u++) \
|
||||
DEBUGLOGRAW(l, "%02X ", ((const unsigned char*)(p))[debug_u]); \
|
||||
DEBUGLOGRAW(l, " \n"); \
|
||||
DEBUGLOGRAW(l, " \n"); \
|
||||
}
|
||||
|
||||
static unsigned long long GetCurrentClockTimeMicroseconds(void)
|
||||
@@ -54,21 +51,21 @@ static unsigned long long GetCurrentClockTimeMicroseconds(void)
|
||||
}
|
||||
|
||||
#define MUTEX_WAIT_TIME_DLEVEL 5
|
||||
#define PTHREAD_MUTEX_LOCK(mutex) \
|
||||
if (g_debugLevel>=MUTEX_WAIT_TIME_DLEVEL) { \
|
||||
unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
|
||||
pthread_mutex_lock(mutex); \
|
||||
{ unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
|
||||
unsigned long long const elapsedTime = (afterTime-beforeTime); \
|
||||
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
|
||||
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
|
||||
elapsedTime, #mutex); \
|
||||
} } \
|
||||
} else pthread_mutex_lock(mutex);
|
||||
#define PTHREAD_MUTEX_LOCK(mutex) { \
|
||||
if (ZSTD_DEBUG>=MUTEX_WAIT_TIME_DLEVEL) { \
|
||||
unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds(); \
|
||||
pthread_mutex_lock(mutex); \
|
||||
{ unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \
|
||||
unsigned long long const elapsedTime = (afterTime-beforeTime); \
|
||||
if (elapsedTime > 1000) { /* or whatever threshold you like; I'm using 1 millisecond here */ \
|
||||
DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL, "Thread took %llu microseconds to acquire mutex %s \n", \
|
||||
elapsedTime, #mutex); \
|
||||
} } \
|
||||
} else pthread_mutex_lock(mutex); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define DEBUGLOG(l, ...) {} /* disabled */
|
||||
# define PTHREAD_MUTEX_LOCK(m) pthread_mutex_lock(m)
|
||||
# define DEBUG_PRINTHEX(l,p,n) {}
|
||||
|
||||
@@ -87,16 +84,19 @@ static const buffer_t g_nullBuffer = { NULL, 0 };
|
||||
typedef struct ZSTDMT_bufferPool_s {
|
||||
unsigned totalBuffers;
|
||||
unsigned nbBuffers;
|
||||
ZSTD_customMem cMem;
|
||||
buffer_t bTable[1]; /* variable size */
|
||||
} ZSTDMT_bufferPool;
|
||||
|
||||
static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads)
|
||||
static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbThreads, ZSTD_customMem cMem)
|
||||
{
|
||||
unsigned const maxNbBuffers = 2*nbThreads + 2;
|
||||
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)calloc(1, sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t));
|
||||
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc(
|
||||
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
|
||||
if (bufPool==NULL) return NULL;
|
||||
bufPool->totalBuffers = maxNbBuffers;
|
||||
bufPool->nbBuffers = 0;
|
||||
bufPool->cMem = cMem;
|
||||
return bufPool;
|
||||
}
|
||||
|
||||
@@ -105,8 +105,21 @@ static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)
|
||||
unsigned u;
|
||||
if (!bufPool) return; /* compatibility with free on NULL */
|
||||
for (u=0; u<bufPool->totalBuffers; u++)
|
||||
free(bufPool->bTable[u].start);
|
||||
free(bufPool);
|
||||
ZSTD_free(bufPool->bTable[u].start, bufPool->cMem);
|
||||
ZSTD_free(bufPool, bufPool->cMem);
|
||||
}
|
||||
|
||||
/* only works at initialization, not during compression */
|
||||
static size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)
|
||||
{
|
||||
size_t const poolSize = sizeof(*bufPool)
|
||||
+ (bufPool->totalBuffers - 1) * sizeof(buffer_t);
|
||||
unsigned u;
|
||||
size_t totalBufferSize = 0;
|
||||
for (u=0; u<bufPool->totalBuffers; u++)
|
||||
totalBufferSize += bufPool->bTable[u].size;
|
||||
|
||||
return poolSize + totalBufferSize;
|
||||
}
|
||||
|
||||
/* assumption : invocation from main thread only ! */
|
||||
@@ -115,13 +128,15 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* pool, size_t bSize)
|
||||
if (pool->nbBuffers) { /* try to use an existing buffer */
|
||||
buffer_t const buf = pool->bTable[--(pool->nbBuffers)];
|
||||
size_t const availBufferSize = buf.size;
|
||||
if ((availBufferSize >= bSize) & (availBufferSize <= 10*bSize)) /* large enough, but not too much */
|
||||
if ((availBufferSize >= bSize) & (availBufferSize <= 10*bSize))
|
||||
/* large enough, but not too much */
|
||||
return buf;
|
||||
free(buf.start); /* size conditions not respected : scratch this buffer and create a new one */
|
||||
/* size conditions not respected : scratch this buffer, create new one */
|
||||
ZSTD_free(buf.start, pool->cMem);
|
||||
}
|
||||
/* create new buffer */
|
||||
{ buffer_t buffer;
|
||||
void* const start = malloc(bSize);
|
||||
void* const start = ZSTD_malloc(bSize, pool->cMem);
|
||||
if (start==NULL) bSize = 0;
|
||||
buffer.start = start; /* note : start can be NULL if malloc fails ! */
|
||||
buffer.size = bSize;
|
||||
@@ -138,7 +153,7 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* pool, buffer_t buf)
|
||||
return;
|
||||
}
|
||||
/* Reached bufferPool capacity (should not happen) */
|
||||
free(buf.start);
|
||||
ZSTD_free(buf.start, pool->cMem);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +162,7 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* pool, buffer_t buf)
|
||||
typedef struct {
|
||||
unsigned totalCCtx;
|
||||
unsigned availCCtx;
|
||||
ZSTD_customMem cMem;
|
||||
ZSTD_CCtx* cctx[1]; /* variable size */
|
||||
} ZSTDMT_CCtxPool;
|
||||
|
||||
@@ -158,23 +174,40 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
|
||||
unsigned u;
|
||||
for (u=0; u<pool->totalCCtx; u++)
|
||||
ZSTD_freeCCtx(pool->cctx[u]); /* note : compatible with free on NULL */
|
||||
free(pool);
|
||||
ZSTD_free(pool, pool->cMem);
|
||||
}
|
||||
|
||||
/* ZSTDMT_createCCtxPool() :
|
||||
* implies nbThreads >= 1 , checked by caller ZSTDMT_createCCtx() */
|
||||
static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads)
|
||||
static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(unsigned nbThreads,
|
||||
ZSTD_customMem cMem)
|
||||
{
|
||||
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) calloc(1, sizeof(ZSTDMT_CCtxPool) + (nbThreads-1)*sizeof(ZSTD_CCtx*));
|
||||
ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc(
|
||||
sizeof(ZSTDMT_CCtxPool) + (nbThreads-1)*sizeof(ZSTD_CCtx*), cMem);
|
||||
if (!cctxPool) return NULL;
|
||||
cctxPool->cMem = cMem;
|
||||
cctxPool->totalCCtx = nbThreads;
|
||||
cctxPool->availCCtx = 1; /* at least one cctx for single-thread mode */
|
||||
cctxPool->cctx[0] = ZSTD_createCCtx();
|
||||
cctxPool->cctx[0] = ZSTD_createCCtx_advanced(cMem);
|
||||
if (!cctxPool->cctx[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }
|
||||
DEBUGLOG(1, "cctxPool created, with %u threads", nbThreads);
|
||||
DEBUGLOG(4, "cctxPool created, with %u threads", nbThreads);
|
||||
return cctxPool;
|
||||
}
|
||||
|
||||
/* only works during initialization phase, not during compression */
|
||||
static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
|
||||
{
|
||||
unsigned const nbThreads = cctxPool->totalCCtx;
|
||||
size_t const poolSize = sizeof(*cctxPool)
|
||||
+ (nbThreads-1)*sizeof(ZSTD_CCtx*);
|
||||
unsigned u;
|
||||
size_t totalCCtxSize = 0;
|
||||
for (u=0; u<nbThreads; u++)
|
||||
totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctx[u]);
|
||||
|
||||
return poolSize + totalCCtxSize;
|
||||
}
|
||||
|
||||
static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* pool)
|
||||
{
|
||||
if (pool->availCCtx) {
|
||||
@@ -218,7 +251,7 @@ typedef struct {
|
||||
pthread_mutex_t* jobCompleted_mutex;
|
||||
pthread_cond_t* jobCompleted_cond;
|
||||
ZSTD_parameters params;
|
||||
ZSTD_CDict* cdict;
|
||||
const ZSTD_CDict* cdict;
|
||||
unsigned long long fullFrameSize;
|
||||
} ZSTDMT_jobDescription;
|
||||
|
||||
@@ -228,11 +261,11 @@ void ZSTDMT_compressChunk(void* jobDescription)
|
||||
ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;
|
||||
const void* const src = (const char*)job->srcStart + job->dictSize;
|
||||
buffer_t const dstBuff = job->dstBuff;
|
||||
DEBUGLOG(3, "job (first:%u) (last:%u) : dictSize %u, srcSize %u",
|
||||
DEBUGLOG(4, "job (first:%u) (last:%u) : dictSize %u, srcSize %u",
|
||||
job->firstChunk, job->lastChunk, (U32)job->dictSize, (U32)job->srcSize);
|
||||
if (job->cdict) { /* should only happen for first segment */
|
||||
size_t const initError = ZSTD_compressBegin_usingCDict_advanced(job->cctx, job->cdict, job->params.fParams, job->fullFrameSize);
|
||||
if (job->cdict) DEBUGLOG(3, "using CDict ");
|
||||
DEBUGLOG(5, "using CDict");
|
||||
if (ZSTD_isError(initError)) { job->cSize = initError; goto _endJob; }
|
||||
} else { /* srcStart points at reloaded section */
|
||||
if (!job->firstChunk) job->params.fParams.contentSizeFlag = 0; /* ensure no srcSize control */
|
||||
@@ -247,12 +280,12 @@ void ZSTDMT_compressChunk(void* jobDescription)
|
||||
ZSTD_invalidateRepCodes(job->cctx);
|
||||
}
|
||||
|
||||
DEBUGLOG(4, "Compressing : ");
|
||||
DEBUGLOG(5, "Compressing : ");
|
||||
DEBUG_PRINTHEX(4, job->srcStart, 12);
|
||||
job->cSize = (job->lastChunk) ?
|
||||
ZSTD_compressEnd (job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize) :
|
||||
ZSTD_compressContinue(job->cctx, dstBuff.start, dstBuff.size, src, job->srcSize);
|
||||
DEBUGLOG(3, "compressed %u bytes into %u bytes (first:%u) (last:%u)",
|
||||
DEBUGLOG(4, "compressed %u bytes into %u bytes (first:%u) (last:%u)",
|
||||
(unsigned)job->srcSize, (unsigned)job->cSize, job->firstChunk, job->lastChunk);
|
||||
DEBUGLOG(5, "dstBuff.size : %u ; => %s", (U32)dstBuff.size, ZSTD_getErrorName(job->cSize));
|
||||
|
||||
@@ -271,6 +304,7 @@ _endJob:
|
||||
|
||||
struct ZSTDMT_CCtx_s {
|
||||
POOL_ctx* factory;
|
||||
ZSTDMT_jobDescription* jobs;
|
||||
ZSTDMT_bufferPool* buffPool;
|
||||
ZSTDMT_CCtxPool* cctxPool;
|
||||
pthread_mutex_t jobCompleted_mutex;
|
||||
@@ -292,43 +326,51 @@ struct ZSTDMT_CCtx_s {
|
||||
unsigned overlapRLog;
|
||||
unsigned long long frameContentSize;
|
||||
size_t sectionSize;
|
||||
ZSTD_CDict* cdict;
|
||||
ZSTD_CStream* cstream;
|
||||
ZSTDMT_jobDescription jobs[1]; /* variable size (must lies at the end) */
|
||||
ZSTD_customMem cMem;
|
||||
ZSTD_CDict* cdictLocal;
|
||||
const ZSTD_CDict* cdict;
|
||||
};
|
||||
|
||||
ZSTDMT_CCtx *ZSTDMT_createCCtx(unsigned nbThreads)
|
||||
ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads, ZSTD_customMem cMem)
|
||||
{
|
||||
ZSTDMT_CCtx* cctx;
|
||||
ZSTDMT_CCtx* mtctx;
|
||||
U32 const minNbJobs = nbThreads + 2;
|
||||
U32 const nbJobsLog2 = ZSTD_highbit32(minNbJobs) + 1;
|
||||
U32 const nbJobs = 1 << nbJobsLog2;
|
||||
DEBUGLOG(5, "nbThreads : %u ; minNbJobs : %u ; nbJobsLog2 : %u ; nbJobs : %u \n",
|
||||
nbThreads, minNbJobs, nbJobsLog2, nbJobs);
|
||||
DEBUGLOG(5, "nbThreads: %u ; minNbJobs: %u ; nbJobsLog2: %u ; nbJobs: %u",
|
||||
nbThreads, minNbJobs, nbJobsLog2, nbJobs);
|
||||
|
||||
if ((nbThreads < 1) | (nbThreads > ZSTDMT_NBTHREADS_MAX)) return NULL;
|
||||
cctx = (ZSTDMT_CCtx*) calloc(1, sizeof(ZSTDMT_CCtx) + nbJobs*sizeof(ZSTDMT_jobDescription));
|
||||
if (!cctx) return NULL;
|
||||
cctx->nbThreads = nbThreads;
|
||||
cctx->jobIDMask = nbJobs - 1;
|
||||
cctx->allJobsCompleted = 1;
|
||||
cctx->sectionSize = 0;
|
||||
cctx->overlapRLog = 3;
|
||||
cctx->factory = POOL_create(nbThreads, 1);
|
||||
cctx->buffPool = ZSTDMT_createBufferPool(nbThreads);
|
||||
cctx->cctxPool = ZSTDMT_createCCtxPool(nbThreads);
|
||||
if (!cctx->factory | !cctx->buffPool | !cctx->cctxPool) { /* one object was not created */
|
||||
ZSTDMT_freeCCtx(cctx);
|
||||
if ((cMem.customAlloc!=NULL) ^ (cMem.customFree!=NULL))
|
||||
/* invalid custom allocator */
|
||||
return NULL;
|
||||
|
||||
mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem);
|
||||
if (!mtctx) return NULL;
|
||||
mtctx->cMem = cMem;
|
||||
mtctx->nbThreads = nbThreads;
|
||||
mtctx->jobIDMask = nbJobs - 1;
|
||||
mtctx->allJobsCompleted = 1;
|
||||
mtctx->sectionSize = 0;
|
||||
mtctx->overlapRLog = 3;
|
||||
mtctx->factory = POOL_create(nbThreads, 1);
|
||||
mtctx->jobs = (ZSTDMT_jobDescription*)ZSTD_calloc(
|
||||
nbJobs * sizeof(*mtctx->jobs), cMem);
|
||||
mtctx->buffPool = ZSTDMT_createBufferPool(nbThreads, cMem);
|
||||
mtctx->cctxPool = ZSTDMT_createCCtxPool(nbThreads, cMem);
|
||||
if (!mtctx->factory | !mtctx->jobs | !mtctx->buffPool | !mtctx->cctxPool) {
|
||||
ZSTDMT_freeCCtx(mtctx);
|
||||
return NULL;
|
||||
}
|
||||
if (nbThreads==1) {
|
||||
cctx->cstream = ZSTD_createCStream();
|
||||
if (!cctx->cstream) {
|
||||
ZSTDMT_freeCCtx(cctx); return NULL;
|
||||
} }
|
||||
pthread_mutex_init(&cctx->jobCompleted_mutex, NULL); /* Todo : check init function return */
|
||||
pthread_cond_init(&cctx->jobCompleted_cond, NULL);
|
||||
DEBUGLOG(4, "mt_cctx created, for %u threads \n", nbThreads);
|
||||
return cctx;
|
||||
pthread_mutex_init(&mtctx->jobCompleted_mutex, NULL); /* Todo : check init function return */
|
||||
pthread_cond_init(&mtctx->jobCompleted_cond, NULL);
|
||||
DEBUGLOG(4, "mt_cctx created, for %u threads", nbThreads);
|
||||
return mtctx;
|
||||
}
|
||||
|
||||
ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbThreads)
|
||||
{
|
||||
return ZSTDMT_createCCtx_advanced(nbThreads, ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
/* ZSTDMT_releaseAllJobResources() :
|
||||
@@ -356,15 +398,26 @@ size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)
|
||||
POOL_free(mtctx->factory);
|
||||
if (!mtctx->allJobsCompleted) ZSTDMT_releaseAllJobResources(mtctx); /* stop workers first */
|
||||
ZSTDMT_freeBufferPool(mtctx->buffPool); /* release job resources into pools first */
|
||||
ZSTD_free(mtctx->jobs, mtctx->cMem);
|
||||
ZSTDMT_freeCCtxPool(mtctx->cctxPool);
|
||||
ZSTD_freeCDict(mtctx->cdict);
|
||||
ZSTD_freeCStream(mtctx->cstream);
|
||||
ZSTD_freeCDict(mtctx->cdictLocal);
|
||||
pthread_mutex_destroy(&mtctx->jobCompleted_mutex);
|
||||
pthread_cond_destroy(&mtctx->jobCompleted_cond);
|
||||
free(mtctx);
|
||||
ZSTD_free(mtctx, mtctx->cMem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)
|
||||
{
|
||||
if (mtctx == NULL) return 0; /* supports sizeof NULL */
|
||||
return sizeof(*mtctx)
|
||||
+ POOL_sizeof(mtctx->factory)
|
||||
+ ZSTDMT_sizeof_bufferPool(mtctx->buffPool)
|
||||
+ (mtctx->jobIDMask+1) * sizeof(ZSTDMT_jobDescription)
|
||||
+ ZSTDMT_sizeof_CCtxPool(mtctx->cctxPool)
|
||||
+ ZSTD_sizeof_CDict(mtctx->cdictLocal);
|
||||
}
|
||||
|
||||
size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value)
|
||||
{
|
||||
switch(parameter)
|
||||
@@ -373,7 +426,7 @@ size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter,
|
||||
mtctx->sectionSize = value;
|
||||
return 0;
|
||||
case ZSTDMT_p_overlapSectionLog :
|
||||
DEBUGLOG(4, "ZSTDMT_p_overlapSectionLog : %u", value);
|
||||
DEBUGLOG(5, "ZSTDMT_p_overlapSectionLog : %u", value);
|
||||
mtctx->overlapRLog = (value >= 9) ? 0 : 9 - value;
|
||||
return 0;
|
||||
default :
|
||||
@@ -404,8 +457,8 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbChunks : (unsigned)(dstCapacity / ZSTD_compressBound(avgChunkSize)); /* presumes avgChunkSize >= 256 KB, which should be the case */
|
||||
size_t frameStartPos = 0, dstBufferPos = 0;
|
||||
|
||||
DEBUGLOG(3, "windowLog : %2u => chunkTargetSize : %u bytes ", params.cParams.windowLog, (U32)chunkTargetSize);
|
||||
DEBUGLOG(2, "nbChunks : %2u (chunkSize : %u bytes) ", nbChunks, (U32)avgChunkSize);
|
||||
DEBUGLOG(4, "windowLog : %2u => chunkTargetSize : %u bytes ", params.cParams.windowLog, (U32)chunkTargetSize);
|
||||
DEBUGLOG(4, "nbChunks : %2u (chunkSize : %u bytes) ", nbChunks, (U32)avgChunkSize);
|
||||
params.fParams.contentSizeFlag = 1;
|
||||
|
||||
if (nbChunks==1) { /* fallback to single-thread mode */
|
||||
@@ -442,8 +495,8 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
mtctx->jobs[u].jobCompleted_mutex = &mtctx->jobCompleted_mutex;
|
||||
mtctx->jobs[u].jobCompleted_cond = &mtctx->jobCompleted_cond;
|
||||
|
||||
DEBUGLOG(3, "posting job %u (%u bytes)", u, (U32)chunkSize);
|
||||
DEBUG_PRINTHEX(3, mtctx->jobs[u].srcStart, 12);
|
||||
DEBUGLOG(4, "posting job %u (%u bytes)", u, (U32)chunkSize);
|
||||
DEBUG_PRINTHEX(5, mtctx->jobs[u].srcStart, 12);
|
||||
POOL_add(mtctx->factory, ZSTDMT_compressChunk, &mtctx->jobs[u]);
|
||||
|
||||
frameStartPos += chunkSize;
|
||||
@@ -455,14 +508,14 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
{ unsigned chunkID;
|
||||
size_t error = 0, dstPos = 0;
|
||||
for (chunkID=0; chunkID<nbChunks; chunkID++) {
|
||||
DEBUGLOG(3, "waiting for chunk %u ", chunkID);
|
||||
DEBUGLOG(5, "waiting for chunk %u ", chunkID);
|
||||
PTHREAD_MUTEX_LOCK(&mtctx->jobCompleted_mutex);
|
||||
while (mtctx->jobs[chunkID].jobCompleted==0) {
|
||||
DEBUGLOG(4, "waiting for jobCompleted signal from chunk %u", chunkID);
|
||||
DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", chunkID);
|
||||
pthread_cond_wait(&mtctx->jobCompleted_cond, &mtctx->jobCompleted_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&mtctx->jobCompleted_mutex);
|
||||
DEBUGLOG(3, "ready to write chunk %u ", chunkID);
|
||||
DEBUGLOG(5, "ready to write chunk %u ", chunkID);
|
||||
|
||||
ZSTDMT_releaseCCtx(mtctx->cctxPool, mtctx->jobs[chunkID].cctx);
|
||||
mtctx->jobs[chunkID].cctx = NULL;
|
||||
@@ -480,7 +533,7 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
dstPos += cSize ;
|
||||
}
|
||||
}
|
||||
if (!error) DEBUGLOG(3, "compressed size : %u ", (U32)dstPos);
|
||||
if (!error) DEBUGLOG(4, "compressed size : %u ", (U32)dstPos);
|
||||
return error ? error : dstPos;
|
||||
}
|
||||
|
||||
@@ -491,12 +544,13 @@ size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
/* ======= Streaming API ======= */
|
||||
/* ====================================== */
|
||||
|
||||
static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs) {
|
||||
static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs)
|
||||
{
|
||||
while (zcs->doneJobID < zcs->nextJobID) {
|
||||
unsigned const jobID = zcs->doneJobID & zcs->jobIDMask;
|
||||
PTHREAD_MUTEX_LOCK(&zcs->jobCompleted_mutex);
|
||||
while (zcs->jobs[jobID].jobCompleted==0) {
|
||||
DEBUGLOG(4, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
|
||||
DEBUGLOG(5, "waiting for jobCompleted signal from chunk %u", zcs->doneJobID); /* we want to block when waiting for data to flush */
|
||||
pthread_cond_wait(&zcs->jobCompleted_cond, &zcs->jobCompleted_mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&zcs->jobCompleted_mutex);
|
||||
@@ -505,33 +559,50 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* zcs) {
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
||||
const void* dict, size_t dictSize, unsigned updateDict,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
||||
const void* dict, size_t dictSize, const ZSTD_CDict* cdict,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
ZSTD_customMem const cmem = { NULL, NULL, NULL };
|
||||
DEBUGLOG(3, "Started new compression, with windowLog : %u", params.cParams.windowLog);
|
||||
if (zcs->nbThreads==1) return ZSTD_initCStream_advanced(zcs->cstream, dict, dictSize, params, pledgedSrcSize);
|
||||
if (zcs->allJobsCompleted == 0) { /* previous job not correctly finished */
|
||||
DEBUGLOG(5, "ZSTDMT_initCStream_internal");
|
||||
/* params are supposed to be fully validated at this point */
|
||||
assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));
|
||||
assert(!((dict) && (cdict))); /* either dict or cdict, not both */
|
||||
|
||||
if (zcs->nbThreads==1) {
|
||||
DEBUGLOG(5, "single thread mode");
|
||||
return ZSTD_initCStream_internal(zcs->cctxPool->cctx[0],
|
||||
dict, dictSize, cdict,
|
||||
params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
if (zcs->allJobsCompleted == 0) { /* previous compression not correctly finished */
|
||||
ZSTDMT_waitForAllJobsCompleted(zcs);
|
||||
ZSTDMT_releaseAllJobResources(zcs);
|
||||
zcs->allJobsCompleted = 1;
|
||||
}
|
||||
|
||||
zcs->params = params;
|
||||
if (updateDict) {
|
||||
ZSTD_freeCDict(zcs->cdict); zcs->cdict = NULL;
|
||||
if (dict && dictSize) {
|
||||
zcs->cdict = ZSTD_createCDict_advanced(dict, dictSize, 0, params.cParams, cmem);
|
||||
if (zcs->cdict == NULL) return ERROR(memory_allocation);
|
||||
} }
|
||||
zcs->frameContentSize = pledgedSrcSize;
|
||||
if (dict) {
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,
|
||||
0 /* byRef */, ZSTD_dm_auto,
|
||||
params.cParams, zcs->cMem);
|
||||
zcs->cdict = zcs->cdictLocal;
|
||||
if (zcs->cdictLocal == NULL) return ERROR(memory_allocation);
|
||||
} else {
|
||||
ZSTD_freeCDict(zcs->cdictLocal);
|
||||
zcs->cdictLocal = NULL;
|
||||
zcs->cdict = cdict;
|
||||
}
|
||||
|
||||
zcs->targetDictSize = (zcs->overlapRLog>=9) ? 0 : (size_t)1 << (zcs->params.cParams.windowLog - zcs->overlapRLog);
|
||||
DEBUGLOG(4, "overlapRLog : %u ", zcs->overlapRLog);
|
||||
DEBUGLOG(3, "overlap Size : %u KB", (U32)(zcs->targetDictSize>>10));
|
||||
DEBUGLOG(5, "overlapRLog : %u ", zcs->overlapRLog);
|
||||
DEBUGLOG(5, "overlap Size : %u KB", (U32)(zcs->targetDictSize>>10));
|
||||
zcs->targetSectionSize = zcs->sectionSize ? zcs->sectionSize : (size_t)1 << (zcs->params.cParams.windowLog + 2);
|
||||
zcs->targetSectionSize = MAX(ZSTDMT_SECTION_SIZE_MIN, zcs->targetSectionSize);
|
||||
zcs->targetSectionSize = MAX(zcs->targetDictSize, zcs->targetSectionSize);
|
||||
DEBUGLOG(3, "Section Size : %u KB", (U32)(zcs->targetSectionSize>>10));
|
||||
DEBUGLOG(5, "Section Size : %u KB", (U32)(zcs->targetSectionSize>>10));
|
||||
zcs->marginSize = zcs->targetSectionSize >> 2;
|
||||
zcs->inBuffSize = zcs->targetDictSize + zcs->targetSectionSize + zcs->marginSize;
|
||||
zcs->inBuff.buffer = ZSTDMT_getBuffer(zcs->buffPool, zcs->inBuffSize);
|
||||
@@ -546,24 +617,39 @@ static size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* zcs,
|
||||
size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
||||
const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
return ZSTDMT_initCStream_internal(zcs, dict, dictSize, 1, params, pledgedSrcSize);
|
||||
DEBUGLOG(5, "ZSTDMT_initCStream_advanced");
|
||||
return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, NULL, params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_frameParameters fParams,
|
||||
unsigned long long pledgedSrcSize)
|
||||
{
|
||||
ZSTD_parameters params = ZSTD_getParamsFromCDict(cdict);
|
||||
if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */
|
||||
params.fParams = fParams;
|
||||
return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, cdict,
|
||||
params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
|
||||
/* ZSTDMT_resetCStream() :
|
||||
* pledgedSrcSize is optional and can be zero == unknown */
|
||||
size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* zcs, unsigned long long pledgedSrcSize)
|
||||
{
|
||||
if (zcs->nbThreads==1) return ZSTD_resetCStream(zcs->cstream, pledgedSrcSize);
|
||||
if (zcs->nbThreads==1)
|
||||
return ZSTD_resetCStream(zcs->cctxPool->cctx[0], pledgedSrcSize);
|
||||
return ZSTDMT_initCStream_internal(zcs, NULL, 0, 0, zcs->params, pledgedSrcSize);
|
||||
}
|
||||
|
||||
size_t ZSTDMT_initCStream(ZSTDMT_CCtx* zcs, int compressionLevel) {
|
||||
ZSTD_parameters const params = ZSTD_getParams(compressionLevel, 0, 0);
|
||||
return ZSTDMT_initCStream_internal(zcs, NULL, 0, 1, params, 0);
|
||||
return ZSTDMT_initCStream_internal(zcs, NULL, 0, NULL, params, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -582,13 +668,16 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsi
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
|
||||
DEBUGLOG(4, "preparing job %u to compress %u bytes with %u preload ", zcs->nextJobID, (U32)srcSize, (U32)zcs->dictSize);
|
||||
DEBUGLOG(4, "preparing job %u to compress %u bytes with %u preload ",
|
||||
zcs->nextJobID, (U32)srcSize, (U32)zcs->dictSize);
|
||||
zcs->jobs[jobID].src = zcs->inBuff.buffer;
|
||||
zcs->jobs[jobID].srcStart = zcs->inBuff.buffer.start;
|
||||
zcs->jobs[jobID].srcSize = srcSize;
|
||||
zcs->jobs[jobID].dictSize = zcs->dictSize; /* note : zcs->inBuff.filled is presumed >= srcSize + dictSize */
|
||||
zcs->jobs[jobID].dictSize = zcs->dictSize;
|
||||
assert(zcs->inBuff.filled >= srcSize + zcs->dictSize);
|
||||
zcs->jobs[jobID].params = zcs->params;
|
||||
if (zcs->nextJobID) zcs->jobs[jobID].params.fParams.checksumFlag = 0; /* do not calculate checksum within sections, just keep it in header for first section */
|
||||
/* do not calculate checksum within sections, but write it in header for first section */
|
||||
if (zcs->nextJobID) zcs->jobs[jobID].params.fParams.checksumFlag = 0;
|
||||
zcs->jobs[jobID].cdict = zcs->nextJobID==0 ? zcs->cdict : NULL;
|
||||
zcs->jobs[jobID].fullFrameSize = zcs->frameContentSize;
|
||||
zcs->jobs[jobID].dstBuff = dstBuffer;
|
||||
@@ -603,6 +692,7 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsi
|
||||
/* get a new buffer for next input */
|
||||
if (!endFrame) {
|
||||
size_t const newDictSize = MIN(srcSize + zcs->dictSize, zcs->targetDictSize);
|
||||
DEBUGLOG(5, "ZSTDMT_createCompressionJob::endFrame = %u", endFrame);
|
||||
zcs->inBuff.buffer = ZSTDMT_getBuffer(zcs->buffPool, zcs->inBuffSize);
|
||||
if (zcs->inBuff.buffer.start == NULL) { /* not enough memory to allocate next input buffer */
|
||||
zcs->jobs[jobID].jobCompleted = 1;
|
||||
@@ -611,22 +701,33 @@ static size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* zcs, size_t srcSize, unsi
|
||||
ZSTDMT_releaseAllJobResources(zcs);
|
||||
return ERROR(memory_allocation);
|
||||
}
|
||||
DEBUGLOG(5, "inBuff filled to %u", (U32)zcs->inBuff.filled);
|
||||
DEBUGLOG(5, "inBuff currently filled to %u", (U32)zcs->inBuff.filled);
|
||||
zcs->inBuff.filled -= srcSize + zcs->dictSize - newDictSize;
|
||||
DEBUGLOG(5, "new job : filled to %u, with %u dict and %u src", (U32)zcs->inBuff.filled, (U32)newDictSize, (U32)(zcs->inBuff.filled - newDictSize));
|
||||
memmove(zcs->inBuff.buffer.start, (const char*)zcs->jobs[jobID].srcStart + zcs->dictSize + srcSize - newDictSize, zcs->inBuff.filled);
|
||||
DEBUGLOG(5, "new job : inBuff filled to %u, with %u dict and %u src",
|
||||
(U32)zcs->inBuff.filled, (U32)newDictSize,
|
||||
(U32)(zcs->inBuff.filled - newDictSize));
|
||||
memmove(zcs->inBuff.buffer.start,
|
||||
(const char*)zcs->jobs[jobID].srcStart + zcs->dictSize + srcSize - newDictSize,
|
||||
zcs->inBuff.filled);
|
||||
DEBUGLOG(5, "new inBuff pre-filled");
|
||||
zcs->dictSize = newDictSize;
|
||||
} else {
|
||||
} else { /* if (endFrame==1) */
|
||||
DEBUGLOG(5, "ZSTDMT_createCompressionJob::endFrame = %u", endFrame);
|
||||
zcs->inBuff.buffer = g_nullBuffer;
|
||||
zcs->inBuff.filled = 0;
|
||||
zcs->dictSize = 0;
|
||||
zcs->frameEnded = 1;
|
||||
if (zcs->nextJobID == 0)
|
||||
zcs->params.fParams.checksumFlag = 0; /* single chunk : checksum is calculated directly within worker thread */
|
||||
/* single chunk exception : checksum is calculated directly within worker thread */
|
||||
zcs->params.fParams.checksumFlag = 0;
|
||||
}
|
||||
|
||||
DEBUGLOG(3, "posting job %u : %u bytes (end:%u) (note : doneJob = %u=>%u)", zcs->nextJobID, (U32)zcs->jobs[jobID].srcSize, zcs->jobs[jobID].lastChunk, zcs->doneJobID, zcs->doneJobID & zcs->jobIDMask);
|
||||
DEBUGLOG(4, "posting job %u : %u bytes (end:%u) (note : doneJob = %u=>%u)",
|
||||
zcs->nextJobID,
|
||||
(U32)zcs->jobs[jobID].srcSize,
|
||||
zcs->jobs[jobID].lastChunk,
|
||||
zcs->doneJobID,
|
||||
zcs->doneJobID & zcs->jobIDMask);
|
||||
POOL_add(zcs->factory, ZSTDMT_compressChunk, &zcs->jobs[jobID]); /* this call is blocking when thread worker pool is exhausted */
|
||||
zcs->nextJobID++;
|
||||
return 0;
|
||||
@@ -664,7 +765,7 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
|
||||
XXH64_update(&zcs->xxhState, (const char*)job.srcStart + job.dictSize, job.srcSize);
|
||||
if (zcs->frameEnded && (zcs->doneJobID+1 == zcs->nextJobID)) { /* write checksum at end of last section */
|
||||
U32 const checksum = (U32)XXH64_digest(&zcs->xxhState);
|
||||
DEBUGLOG(4, "writing checksum : %08X \n", checksum);
|
||||
DEBUGLOG(5, "writing checksum : %08X \n", checksum);
|
||||
MEM_writeLE32((char*)job.dstBuff.start + job.cSize, checksum);
|
||||
job.cSize += 4;
|
||||
zcs->jobs[wJobID].cSize += 4;
|
||||
@@ -675,7 +776,7 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
|
||||
zcs->jobs[wJobID].jobScanned = 1;
|
||||
}
|
||||
{ size_t const toWrite = MIN(job.cSize - job.dstFlushed, output->size - output->pos);
|
||||
DEBUGLOG(4, "Flushing %u bytes from job %u ", (U32)toWrite, zcs->doneJobID);
|
||||
DEBUGLOG(5, "Flushing %u bytes from job %u ", (U32)toWrite, zcs->doneJobID);
|
||||
memcpy((char*)output->dst + output->pos, (const char*)job.dstBuff.start + job.dstFlushed, toWrite);
|
||||
output->pos += toWrite;
|
||||
job.dstFlushed += toWrite;
|
||||
@@ -699,23 +800,29 @@ static size_t ZSTDMT_flushNextJob(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, unsi
|
||||
size_t ZSTDMT_compressStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||
{
|
||||
size_t const newJobThreshold = zcs->dictSize + zcs->targetSectionSize + zcs->marginSize;
|
||||
if (zcs->frameEnded) return ERROR(stage_wrong); /* current frame being ended. Only flush is allowed. Restart with init */
|
||||
if (zcs->nbThreads==1) return ZSTD_compressStream(zcs->cstream, output, input);
|
||||
if (zcs->frameEnded) {
|
||||
/* current frame being ended. Only flush is allowed. Or start new job with init */
|
||||
DEBUGLOG(5, "ZSTDMT_compressStream: zcs::frameEnded==1");
|
||||
return ERROR(stage_wrong);
|
||||
}
|
||||
if (zcs->nbThreads==1) {
|
||||
return ZSTD_compressStream(zcs->cctxPool->cctx[0], output, input);
|
||||
}
|
||||
|
||||
/* fill input buffer */
|
||||
{ size_t const toLoad = MIN(input->size - input->pos, zcs->inBuffSize - zcs->inBuff.filled);
|
||||
memcpy((char*)zcs->inBuff.buffer.start + zcs->inBuff.filled, input->src, toLoad);
|
||||
memcpy((char*)zcs->inBuff.buffer.start + zcs->inBuff.filled, (const char*)input->src + input->pos, toLoad);
|
||||
input->pos += toLoad;
|
||||
zcs->inBuff.filled += toLoad;
|
||||
}
|
||||
|
||||
if ( (zcs->inBuff.filled >= newJobThreshold) /* filled enough : let's compress */
|
||||
&& (zcs->nextJobID <= zcs->doneJobID + zcs->jobIDMask) ) { /* avoid overwriting job round buffer */
|
||||
CHECK_F( ZSTDMT_createCompressionJob(zcs, zcs->targetSectionSize, 0) );
|
||||
CHECK_F( ZSTDMT_createCompressionJob(zcs, zcs->targetSectionSize, 0 /* endFrame */) );
|
||||
}
|
||||
|
||||
/* check for data to flush */
|
||||
CHECK_F( ZSTDMT_flushNextJob(zcs, output, (zcs->inBuff.filled == zcs->inBuffSize)) ); /* block if it wasn't possible to create new job due to saturation */
|
||||
CHECK_F( ZSTDMT_flushNextJob(zcs, output, (zcs->inBuff.filled == zcs->inBuffSize) /* blockToFlush */) ); /* block if it wasn't possible to create new job due to saturation */
|
||||
|
||||
/* recommended next input size : fill current input buffer */
|
||||
return zcs->inBuffSize - zcs->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */
|
||||
@@ -726,26 +833,60 @@ static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* outp
|
||||
{
|
||||
size_t const srcSize = zcs->inBuff.filled - zcs->dictSize;
|
||||
|
||||
if (srcSize) DEBUGLOG(4, "flushing : %u bytes left to compress", (U32)srcSize);
|
||||
if (srcSize)
|
||||
DEBUGLOG(5, "ZSTDMT_flushStream_internal : %u bytes left to compress",
|
||||
(U32)srcSize);
|
||||
if ( ((srcSize > 0) || (endFrame && !zcs->frameEnded))
|
||||
&& (zcs->nextJobID <= zcs->doneJobID + zcs->jobIDMask) ) {
|
||||
DEBUGLOG(5, "create new job with %u bytes to compress", (U32)srcSize);
|
||||
DEBUGLOG(5, "end order : %u", endFrame);
|
||||
CHECK_F( ZSTDMT_createCompressionJob(zcs, srcSize, endFrame) );
|
||||
DEBUGLOG(5, "resulting zcs->frameEnded : %u", zcs->frameEnded);
|
||||
}
|
||||
|
||||
/* check if there is any data available to flush */
|
||||
DEBUGLOG(5, "zcs->doneJobID : %u ; zcs->nextJobID : %u ", zcs->doneJobID, zcs->nextJobID);
|
||||
return ZSTDMT_flushNextJob(zcs, output, 1);
|
||||
DEBUGLOG(5, "zcs->doneJobID : %u ; zcs->nextJobID : %u",
|
||||
zcs->doneJobID, zcs->nextJobID);
|
||||
return ZSTDMT_flushNextJob(zcs, output, 1 /*blockToFlush */);
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTDMT_flushStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
|
||||
{
|
||||
if (zcs->nbThreads==1) return ZSTD_flushStream(zcs->cstream, output);
|
||||
return ZSTDMT_flushStream_internal(zcs, output, 0);
|
||||
DEBUGLOG(5, "ZSTDMT_flushStream");
|
||||
if (zcs->nbThreads==1)
|
||||
return ZSTD_flushStream(zcs->cctxPool->cctx[0], output);
|
||||
return ZSTDMT_flushStream_internal(zcs, output, 0 /* endFrame */);
|
||||
}
|
||||
|
||||
size_t ZSTDMT_endStream(ZSTDMT_CCtx* zcs, ZSTD_outBuffer* output)
|
||||
{
|
||||
if (zcs->nbThreads==1) return ZSTD_endStream(zcs->cstream, output);
|
||||
return ZSTDMT_flushStream_internal(zcs, output, 1);
|
||||
DEBUGLOG(5, "ZSTDMT_endStream");
|
||||
if (zcs->nbThreads==1)
|
||||
return ZSTD_endStream(zcs->cctxPool->cctx[0], output);
|
||||
return ZSTDMT_flushStream_internal(zcs, output, 1 /* endFrame */);
|
||||
}
|
||||
|
||||
size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp)
|
||||
{
|
||||
DEBUGLOG(5, "in: pos:%u / size:%u ; endOp=%u",
|
||||
(U32)input->pos, (U32)input->size, (U32)endOp);
|
||||
if (input->pos < input->size) /* exclude final flushes */
|
||||
CHECK_F(ZSTDMT_compressStream(mtctx, output, input));
|
||||
if (input->pos < input->size) endOp = ZSTD_e_continue;
|
||||
switch(endOp)
|
||||
{
|
||||
case ZSTD_e_flush:
|
||||
return ZSTDMT_flushStream(mtctx, output);
|
||||
case ZSTD_e_end:
|
||||
DEBUGLOG(5, "endOp:%u; calling ZSTDMT_endStream", (U32)endOp);
|
||||
return ZSTDMT_endStream(mtctx, output);
|
||||
case ZSTD_e_continue:
|
||||
return 1;
|
||||
default:
|
||||
return ERROR(GENERIC); /* invalid endDirective */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,25 +15,33 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Note : All prototypes defined in this file shall be considered experimental.
|
||||
* There is no guarantee of API continuity (yet) on any of these prototypes */
|
||||
/* Note : All prototypes defined in this file are labelled experimental.
|
||||
* No guarantee of API continuity is provided on any of them.
|
||||
* In fact, the expectation is that these prototypes will be replaced
|
||||
* by ZSTD_compress_generic() API in the near future */
|
||||
|
||||
/* === Dependencies === */
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stddef.h> /* size_t */
|
||||
#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */
|
||||
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
|
||||
#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */
|
||||
|
||||
|
||||
/* === Simple one-pass functions === */
|
||||
|
||||
/* === Memory management === */
|
||||
typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;
|
||||
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbThreads);
|
||||
ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* cctx);
|
||||
ZSTDLIB_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbThreads,
|
||||
ZSTD_customMem cMem);
|
||||
ZSTDLIB_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);
|
||||
|
||||
|
||||
/* === Simple buffer-to-butter one-pass function === */
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
int compressionLevel);
|
||||
|
||||
|
||||
/* === Streaming functions === */
|
||||
@@ -53,8 +61,15 @@ ZSTDLIB_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output);
|
||||
# define ZSTDMT_SECTION_SIZE_MIN (1U << 20) /* 1 MB - Minimum size of each compression job */
|
||||
#endif
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx, const void* dict, size_t dictSize, /**< dict can be released after init, a local copy is preserved within zcs */
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be zero == unknown */
|
||||
ZSTDLIB_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx,
|
||||
const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */
|
||||
ZSTD_parameters params,
|
||||
unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */
|
||||
|
||||
ZSTDLIB_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx,
|
||||
const ZSTD_CDict* cdict,
|
||||
ZSTD_frameParameters fparams,
|
||||
unsigned long long pledgedSrcSize); /* note : zero means empty */
|
||||
|
||||
/* ZSDTMT_parameter :
|
||||
* List of parameters that can be set using ZSTDMT_setMTCtxParameter() */
|
||||
@@ -71,6 +86,19 @@ typedef enum {
|
||||
ZSTDLIB_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSDTMT_parameter parameter, unsigned value);
|
||||
|
||||
|
||||
/*! ZSTDMT_compressStream_generic() :
|
||||
* Combines ZSTDMT_compressStream() with ZSTDMT_flushStream() or ZSTDMT_endStream()
|
||||
* depending on flush directive.
|
||||
* @return : minimum amount of data still to be flushed
|
||||
* 0 if fully flushed
|
||||
* or an error code */
|
||||
ZSTDLIB_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp);
|
||||
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
+294
-235
@@ -53,8 +53,7 @@
|
||||
# include "zstd_legacy.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) && !defined(_M_IA64) /* _mm_prefetch() is not defined for ia64 */
|
||||
# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
|
||||
# define ZSTD_PREFETCH(ptr) _mm_prefetch((const char*)ptr, _MM_HINT_T0)
|
||||
#elif defined(__GNUC__)
|
||||
@@ -63,8 +62,9 @@
|
||||
# define ZSTD_PREFETCH(ptr) /* disabled */
|
||||
#endif
|
||||
|
||||
|
||||
/*-*************************************
|
||||
* Macros
|
||||
* Errors
|
||||
***************************************/
|
||||
#define ZSTD_isError ERR_isError /* for inlining */
|
||||
#define FSE_isError ERR_isError
|
||||
@@ -85,6 +85,9 @@ typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
|
||||
ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
|
||||
ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
|
||||
|
||||
typedef enum { zdss_init=0, zdss_loadHeader,
|
||||
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
||||
|
||||
typedef struct {
|
||||
FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
|
||||
FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
|
||||
@@ -117,11 +120,39 @@ struct ZSTD_DCtx_s
|
||||
ZSTD_customMem customMem;
|
||||
size_t litSize;
|
||||
size_t rleSize;
|
||||
BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
|
||||
size_t staticSize;
|
||||
|
||||
/* streaming */
|
||||
ZSTD_DDict* ddictLocal;
|
||||
const ZSTD_DDict* ddict;
|
||||
ZSTD_dStreamStage streamStage;
|
||||
char* inBuff;
|
||||
size_t inBuffSize;
|
||||
size_t inPos;
|
||||
size_t maxWindowSize;
|
||||
char* outBuff;
|
||||
size_t outBuffSize;
|
||||
size_t outStart;
|
||||
size_t outEnd;
|
||||
size_t blockSize;
|
||||
size_t lhSize;
|
||||
void* legacyContext;
|
||||
U32 previousLegacyVersion;
|
||||
U32 legacyVersion;
|
||||
U32 hostageByte;
|
||||
|
||||
/* workspace */
|
||||
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
|
||||
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
|
||||
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
|
||||
|
||||
size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx) { return (dctx==NULL) ? 0 : sizeof(ZSTD_DCtx); }
|
||||
size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
|
||||
{
|
||||
if (dctx==NULL) return 0; /* support sizeof NULL */
|
||||
return sizeof(*dctx)
|
||||
+ ZSTD_sizeof_DDict(dctx->ddictLocal)
|
||||
+ dctx->inBuffSize + dctx->outBuffSize;
|
||||
}
|
||||
|
||||
size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
|
||||
|
||||
@@ -145,36 +176,73 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
||||
{
|
||||
ZSTD_decompressBegin(dctx); /* cannot fail */
|
||||
dctx->staticSize = 0;
|
||||
dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
||||
dctx->ddict = NULL;
|
||||
dctx->ddictLocal = NULL;
|
||||
dctx->inBuff = NULL;
|
||||
dctx->inBuffSize = 0;
|
||||
dctx->outBuffSize= 0;
|
||||
dctx->streamStage = zdss_init;
|
||||
}
|
||||
|
||||
ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
|
||||
{
|
||||
ZSTD_DCtx* dctx;
|
||||
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
||||
|
||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem);
|
||||
if (!dctx) return NULL;
|
||||
dctx->customMem = customMem;
|
||||
dctx->legacyContext = NULL;
|
||||
ZSTD_initDCtx_internal(dctx);
|
||||
return dctx;
|
||||
}
|
||||
}
|
||||
|
||||
dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem);
|
||||
if (!dctx) return NULL;
|
||||
memcpy(&dctx->customMem, &customMem, sizeof(customMem));
|
||||
ZSTD_decompressBegin(dctx);
|
||||
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
||||
{
|
||||
ZSTD_DCtx* dctx = (ZSTD_DCtx*) workspace;
|
||||
|
||||
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
||||
if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
|
||||
|
||||
ZSTD_initDCtx_internal(dctx);
|
||||
dctx->staticSize = workspaceSize;
|
||||
dctx->inBuff = (char*)(dctx+1);
|
||||
return dctx;
|
||||
}
|
||||
|
||||
ZSTD_DCtx* ZSTD_createDCtx(void)
|
||||
{
|
||||
return ZSTD_createDCtx_advanced(defaultCustomMem);
|
||||
return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
|
||||
{
|
||||
if (dctx==NULL) return 0; /* support free on NULL */
|
||||
ZSTD_free(dctx, dctx->customMem);
|
||||
return 0; /* reserved as a potential error code in the future */
|
||||
if (dctx->staticSize) return ERROR(memory_allocation); /* not compatible with static DCtx */
|
||||
{ ZSTD_customMem const cMem = dctx->customMem;
|
||||
ZSTD_freeDDict(dctx->ddictLocal);
|
||||
dctx->ddictLocal = NULL;
|
||||
ZSTD_free(dctx->inBuff, cMem);
|
||||
dctx->inBuff = NULL;
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
if (dctx->legacyContext)
|
||||
ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);
|
||||
#endif
|
||||
ZSTD_free(dctx, cMem);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* no longer useful */
|
||||
void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
|
||||
{
|
||||
size_t const workSpaceSize = (ZSTD_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH) + ZSTD_frameHeaderSize_max;
|
||||
memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
|
||||
size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
|
||||
memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
|
||||
}
|
||||
|
||||
|
||||
@@ -230,7 +298,8 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
|
||||
if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {
|
||||
if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
/* skippable frame */
|
||||
if (srcSize < ZSTD_skippableHeaderSize) return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */
|
||||
if (srcSize < ZSTD_skippableHeaderSize)
|
||||
return ZSTD_skippableHeaderSize; /* magic number + frame length */
|
||||
memset(zfhPtr, 0, sizeof(*zfhPtr));
|
||||
zfhPtr->frameContentSize = MEM_readLE32((const char *)src + 4);
|
||||
zfhPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
|
||||
@@ -253,11 +322,13 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
|
||||
U32 windowSize = 0;
|
||||
U32 dictID = 0;
|
||||
U64 frameContentSize = 0;
|
||||
if ((fhdByte & 0x08) != 0) return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */
|
||||
if ((fhdByte & 0x08) != 0)
|
||||
return ERROR(frameParameter_unsupported); /* reserved bits, must be zero */
|
||||
if (!singleSegment) {
|
||||
BYTE const wlByte = ip[pos++];
|
||||
U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
|
||||
if (windowLog > ZSTD_WINDOWLOG_MAX) return ERROR(frameParameter_windowTooLarge); /* avoids issue with 1 << windowLog */
|
||||
if (windowLog > ZSTD_WINDOWLOG_MAX)
|
||||
return ERROR(frameParameter_windowTooLarge);
|
||||
windowSize = (1U << windowLog);
|
||||
windowSize += (windowSize >> 3) * (wlByte&7);
|
||||
}
|
||||
@@ -321,51 +392,48 @@ unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
|
||||
* @return : decompressed size of the frames contained */
|
||||
unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
|
||||
{
|
||||
{
|
||||
unsigned long long totalDstSize = 0;
|
||||
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
|
||||
const U32 magicNumber = MEM_readLE32(src);
|
||||
unsigned long long totalDstSize = 0;
|
||||
|
||||
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
size_t skippableSize;
|
||||
if (srcSize < ZSTD_skippableHeaderSize)
|
||||
return ERROR(srcSize_wrong);
|
||||
skippableSize = MEM_readLE32((const BYTE *)src + 4) +
|
||||
ZSTD_skippableHeaderSize;
|
||||
if (srcSize < skippableSize) {
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
while (srcSize >= ZSTD_frameHeaderSize_prefix) {
|
||||
const U32 magicNumber = MEM_readLE32(src);
|
||||
|
||||
src = (const BYTE *)src + skippableSize;
|
||||
srcSize -= skippableSize;
|
||||
continue;
|
||||
if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
|
||||
size_t skippableSize;
|
||||
if (srcSize < ZSTD_skippableHeaderSize)
|
||||
return ERROR(srcSize_wrong);
|
||||
skippableSize = MEM_readLE32((const BYTE *)src + 4) +
|
||||
ZSTD_skippableHeaderSize;
|
||||
if (srcSize < skippableSize) {
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
||||
if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
|
||||
|
||||
/* check for overflow */
|
||||
if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
|
||||
totalDstSize += ret;
|
||||
}
|
||||
{
|
||||
size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
||||
if (ZSTD_isError(frameSrcSize)) {
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
src = (const BYTE *)src + frameSrcSize;
|
||||
srcSize -= frameSrcSize;
|
||||
}
|
||||
src = (const BYTE *)src + skippableSize;
|
||||
srcSize -= skippableSize;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (srcSize) {
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
{ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
|
||||
if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
|
||||
|
||||
return totalDstSize;
|
||||
/* check for overflow */
|
||||
if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
|
||||
totalDstSize += ret;
|
||||
}
|
||||
{ size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
|
||||
if (ZSTD_isError(frameSrcSize)) {
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
src = (const BYTE *)src + frameSrcSize;
|
||||
srcSize -= frameSrcSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (srcSize) {
|
||||
return ZSTD_CONTENTSIZE_ERROR;
|
||||
}
|
||||
|
||||
return totalDstSize;
|
||||
}
|
||||
|
||||
/** ZSTD_getDecompressedSize() :
|
||||
@@ -483,7 +551,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
litCSize = (lhc >> 22) + (istart[4] << 10);
|
||||
break;
|
||||
}
|
||||
if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
|
||||
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
||||
if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);
|
||||
|
||||
if (HUF_isError((litEncType==set_repeat) ?
|
||||
@@ -555,7 +623,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
|
||||
if (srcSize<4) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
|
||||
break;
|
||||
}
|
||||
if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);
|
||||
if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
|
||||
memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
|
||||
dctx->litPtr = dctx->litBuffer;
|
||||
dctx->litSize = litSize;
|
||||
@@ -1288,7 +1356,7 @@ static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
|
||||
{ /* blockType == blockCompressed */
|
||||
const BYTE* ip = (const BYTE*)src;
|
||||
|
||||
if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);
|
||||
if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
|
||||
|
||||
/* Decode literals section */
|
||||
{ size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
|
||||
@@ -1503,6 +1571,8 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
|
||||
size_t decodedSize;
|
||||
size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);
|
||||
if (ZSTD_isError(frameSize)) return frameSize;
|
||||
/* legacy support is incompatible with static dctx */
|
||||
if (dctx->staticSize) return ERROR(memory_allocation);
|
||||
|
||||
decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);
|
||||
|
||||
@@ -1578,7 +1648,7 @@ size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const
|
||||
|
||||
size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
|
||||
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
|
||||
size_t regenSize;
|
||||
ZSTD_DCtx* const dctx = ZSTD_createDCtx();
|
||||
if (dctx==NULL) return ERROR(memory_allocation);
|
||||
@@ -1619,21 +1689,22 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
|
||||
}
|
||||
}
|
||||
|
||||
int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */
|
||||
static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
|
||||
|
||||
/** ZSTD_decompressContinue() :
|
||||
* @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
|
||||
* or an error code, which can be tested using ZSTD_isError() */
|
||||
* srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
|
||||
* @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
|
||||
* or an error code, which can be tested using ZSTD_isError() */
|
||||
size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
|
||||
if (srcSize != dctx->expected) return ERROR(srcSize_wrong); /* unauthorized */
|
||||
if (dstCapacity) ZSTD_checkContinuity(dctx, dst);
|
||||
|
||||
switch (dctx->stage)
|
||||
{
|
||||
case ZSTDds_getFrameHeaderSize :
|
||||
if (srcSize != ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong); /* impossible */
|
||||
if (srcSize != ZSTD_frameHeaderSize_prefix) return ERROR(srcSize_wrong); /* unauthorized */
|
||||
if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
||||
memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
|
||||
dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */
|
||||
@@ -1678,7 +1749,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
|
||||
dctx->stage = ZSTDds_getFrameHeaderSize;
|
||||
}
|
||||
} else {
|
||||
dctx->expected = 3; /* go directly to next header */
|
||||
dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */
|
||||
dctx->stage = ZSTDds_decodeBlockHeader;
|
||||
}
|
||||
return 0;
|
||||
@@ -1904,33 +1975,39 @@ static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict* ddict)
|
||||
}
|
||||
|
||||
|
||||
static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, const void* dict, size_t dictSize, unsigned byReference)
|
||||
{
|
||||
if ((byReference) || (!dict) || (!dictSize)) {
|
||||
ddict->dictBuffer = NULL;
|
||||
ddict->dictContent = dict;
|
||||
} else {
|
||||
void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem);
|
||||
ddict->dictBuffer = internalBuffer;
|
||||
ddict->dictContent = internalBuffer;
|
||||
if (!internalBuffer) return ERROR(memory_allocation);
|
||||
memcpy(internalBuffer, dict, dictSize);
|
||||
}
|
||||
ddict->dictSize = dictSize;
|
||||
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
||||
|
||||
/* parse dictionary content */
|
||||
CHECK_F( ZSTD_loadEntropy_inDDict(ddict) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
|
||||
{
|
||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||
if (!customMem.customAlloc ^ !customMem.customFree) return NULL;
|
||||
|
||||
{ ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
|
||||
if (!ddict) return NULL;
|
||||
ddict->cMem = customMem;
|
||||
|
||||
if ((byReference) || (!dict) || (!dictSize)) {
|
||||
ddict->dictBuffer = NULL;
|
||||
ddict->dictContent = dict;
|
||||
} else {
|
||||
void* const internalBuffer = ZSTD_malloc(dictSize, customMem);
|
||||
if (!internalBuffer) { ZSTD_freeDDict(ddict); return NULL; }
|
||||
memcpy(internalBuffer, dict, dictSize);
|
||||
ddict->dictBuffer = internalBuffer;
|
||||
ddict->dictContent = internalBuffer;
|
||||
if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, byReference) )) {
|
||||
ZSTD_freeDDict(ddict);
|
||||
return NULL;
|
||||
}
|
||||
ddict->dictSize = dictSize;
|
||||
ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
|
||||
/* parse dictionary content */
|
||||
{ size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict);
|
||||
if (ZSTD_isError(errorCode)) {
|
||||
ZSTD_freeDDict(ddict);
|
||||
return NULL;
|
||||
} }
|
||||
|
||||
return ddict;
|
||||
}
|
||||
@@ -1946,7 +2023,6 @@ ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
|
||||
return ZSTD_createDDict_advanced(dict, dictSize, 0, allocator);
|
||||
}
|
||||
|
||||
|
||||
/*! ZSTD_createDDict_byReference() :
|
||||
* Create a digested dictionary, to start decompression without startup delay.
|
||||
* Dictionary content is simply referenced, it will be accessed during decompression.
|
||||
@@ -1958,6 +2034,24 @@ ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize
|
||||
}
|
||||
|
||||
|
||||
ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
|
||||
const void* dict, size_t dictSize,
|
||||
unsigned byReference)
|
||||
{
|
||||
size_t const neededSpace = sizeof(ZSTD_DDict) + (byReference ? 0 : dictSize);
|
||||
ZSTD_DDict* const ddict = (ZSTD_DDict*)workspace;
|
||||
if ((size_t)workspace & 7) return NULL; /* 8-aligned */
|
||||
if (workspaceSize < neededSpace) return NULL;
|
||||
if (!byReference) {
|
||||
memcpy(ddict+1, dict, dictSize); /* local copy */
|
||||
dict = ddict+1;
|
||||
}
|
||||
if (ZSTD_isError( ZSTD_initDDict_internal(ddict, dict, dictSize, 1 /* byRef */) ))
|
||||
return NULL;
|
||||
return ddict;
|
||||
}
|
||||
|
||||
|
||||
size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
||||
{
|
||||
if (ddict==NULL) return 0; /* support free on NULL */
|
||||
@@ -1970,10 +2064,10 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
|
||||
|
||||
/*! ZSTD_estimateDDictSize() :
|
||||
* Estimate amount of memory that will be needed to create a dictionary for decompression.
|
||||
* Note : if dictionary is created "byReference", reduce this amount by dictSize */
|
||||
size_t ZSTD_estimateDDictSize(size_t dictSize)
|
||||
* Note : dictionary created "byReference" are smaller */
|
||||
size_t ZSTD_estimateDDictSize(size_t dictSize, unsigned byReference)
|
||||
{
|
||||
return dictSize + sizeof(ZSTD_DDict);
|
||||
return sizeof(ZSTD_DDict) + (byReference ? 0 : dictSize);
|
||||
}
|
||||
|
||||
size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
|
||||
@@ -2044,88 +2138,30 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
||||
* Streaming decompression
|
||||
*====================================*/
|
||||
|
||||
typedef enum { zdss_init, zdss_loadHeader,
|
||||
zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
|
||||
|
||||
/* *** Resource management *** */
|
||||
struct ZSTD_DStream_s {
|
||||
ZSTD_DCtx* dctx;
|
||||
ZSTD_DDict* ddictLocal;
|
||||
const ZSTD_DDict* ddict;
|
||||
ZSTD_frameHeader fParams;
|
||||
ZSTD_dStreamStage stage;
|
||||
char* inBuff;
|
||||
size_t inBuffSize;
|
||||
size_t inPos;
|
||||
size_t maxWindowSize;
|
||||
char* outBuff;
|
||||
size_t outBuffSize;
|
||||
size_t outStart;
|
||||
size_t outEnd;
|
||||
size_t blockSize;
|
||||
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
|
||||
size_t lhSize;
|
||||
ZSTD_customMem customMem;
|
||||
void* legacyContext;
|
||||
U32 previousLegacyVersion;
|
||||
U32 legacyVersion;
|
||||
U32 hostageByte;
|
||||
}; /* typedef'd to ZSTD_DStream within "zstd.h" */
|
||||
|
||||
|
||||
ZSTD_DStream* ZSTD_createDStream(void)
|
||||
{
|
||||
return ZSTD_createDStream_advanced(defaultCustomMem);
|
||||
return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
|
||||
}
|
||||
|
||||
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
|
||||
{
|
||||
ZSTD_DStream* zds;
|
||||
|
||||
if (!customMem.customAlloc && !customMem.customFree) customMem = defaultCustomMem;
|
||||
if (!customMem.customAlloc || !customMem.customFree) return NULL;
|
||||
|
||||
zds = (ZSTD_DStream*) ZSTD_malloc(sizeof(ZSTD_DStream), customMem);
|
||||
if (zds==NULL) return NULL;
|
||||
memset(zds, 0, sizeof(ZSTD_DStream));
|
||||
memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem));
|
||||
zds->dctx = ZSTD_createDCtx_advanced(customMem);
|
||||
if (zds->dctx == NULL) { ZSTD_freeDStream(zds); return NULL; }
|
||||
zds->stage = zdss_init;
|
||||
zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
|
||||
return zds;
|
||||
return ZSTD_createDCtx_advanced(customMem);
|
||||
}
|
||||
|
||||
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
|
||||
{
|
||||
if (zds==NULL) return 0; /* support free on null */
|
||||
{ ZSTD_customMem const cMem = zds->customMem;
|
||||
ZSTD_freeDCtx(zds->dctx);
|
||||
zds->dctx = NULL;
|
||||
ZSTD_freeDDict(zds->ddictLocal);
|
||||
zds->ddictLocal = NULL;
|
||||
ZSTD_free(zds->inBuff, cMem);
|
||||
zds->inBuff = NULL;
|
||||
ZSTD_free(zds->outBuff, cMem);
|
||||
zds->outBuff = NULL;
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)
|
||||
if (zds->legacyContext)
|
||||
ZSTD_freeLegacyStreamContext(zds->legacyContext, zds->previousLegacyVersion);
|
||||
#endif
|
||||
ZSTD_free(zds, cMem);
|
||||
return 0;
|
||||
}
|
||||
return ZSTD_freeDCtx(zds);
|
||||
}
|
||||
|
||||
|
||||
/* *** Initialization *** */
|
||||
|
||||
size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; }
|
||||
size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
|
||||
size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
|
||||
size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
|
||||
|
||||
size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
|
||||
{
|
||||
zds->stage = zdss_loadHeader;
|
||||
zds->streamStage = zdss_loadHeader;
|
||||
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
||||
ZSTD_freeDDict(zds->ddictLocal);
|
||||
if (dict && dictSize >= 8) {
|
||||
@@ -2154,7 +2190,7 @@ size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict)
|
||||
|
||||
size_t ZSTD_resetDStream(ZSTD_DStream* zds)
|
||||
{
|
||||
zds->stage = zdss_loadHeader;
|
||||
zds->streamStage = zdss_loadHeader;
|
||||
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
||||
zds->legacyVersion = 0;
|
||||
zds->hostageByte = 0;
|
||||
@@ -2175,17 +2211,13 @@ size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
|
||||
|
||||
size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
|
||||
{
|
||||
if (zds==NULL) return 0; /* support sizeof NULL */
|
||||
return sizeof(*zds)
|
||||
+ ZSTD_sizeof_DCtx(zds->dctx)
|
||||
+ ZSTD_sizeof_DDict(zds->ddictLocal)
|
||||
+ zds->inBuffSize + zds->outBuffSize;
|
||||
return ZSTD_sizeof_DCtx(zds);
|
||||
}
|
||||
|
||||
size_t ZSTD_estimateDStreamSize(ZSTD_frameHeader fHeader)
|
||||
{
|
||||
size_t const windowSize = fHeader.windowSize;
|
||||
size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
|
||||
size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
|
||||
size_t const inBuffSize = blockSize; /* no block can be larger */
|
||||
size_t const outBuffSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
|
||||
return sizeof(ZSTD_DStream) + ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
|
||||
@@ -2212,13 +2244,18 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
char* op = ostart;
|
||||
U32 someMoreWork = 1;
|
||||
|
||||
DEBUGLOG(5, "ZSTD_decompressStream");
|
||||
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||
if (zds->legacyVersion)
|
||||
if (zds->legacyVersion) {
|
||||
/* legacy support is incompatible with static dctx */
|
||||
if (zds->staticSize) return ERROR(memory_allocation);
|
||||
return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (someMoreWork) {
|
||||
switch(zds->stage)
|
||||
switch(zds->streamStage)
|
||||
{
|
||||
case zdss_init :
|
||||
ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
|
||||
@@ -2226,22 +2263,25 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
|
||||
case zdss_loadHeader :
|
||||
{ size_t const hSize = ZSTD_getFrameHeader(&zds->fParams, zds->headerBuffer, zds->lhSize);
|
||||
if (ZSTD_isError(hSize))
|
||||
if (ZSTD_isError(hSize)) {
|
||||
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
|
||||
{ U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
||||
U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);
|
||||
if (legacyVersion) {
|
||||
const void* const dict = zds->ddict ? zds->ddict->dictContent : NULL;
|
||||
size_t const dictSize = zds->ddict ? zds->ddict->dictSize : 0;
|
||||
/* legacy support is incompatible with static dctx */
|
||||
if (zds->staticSize) return ERROR(memory_allocation);
|
||||
CHECK_F(ZSTD_initLegacyStream(&zds->legacyContext, zds->previousLegacyVersion, legacyVersion,
|
||||
dict, dictSize));
|
||||
zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;
|
||||
return ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);
|
||||
} else {
|
||||
return hSize; /* error */
|
||||
} }
|
||||
}
|
||||
#else
|
||||
return hSize;
|
||||
#endif
|
||||
}
|
||||
if (hSize != 0) { /* need more input */
|
||||
size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
|
||||
if (toLoad > (size_t)(iend-ip)) { /* not enough input to load full header */
|
||||
@@ -2252,82 +2292,97 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
}
|
||||
memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
|
||||
break;
|
||||
}
|
||||
} }
|
||||
|
||||
/* check for single-pass mode opportunity */
|
||||
if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
|
||||
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
||||
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
||||
if (cSize <= (size_t)(iend-istart)) {
|
||||
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend-op, istart, cSize, zds->ddict);
|
||||
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
||||
ip = istart + cSize;
|
||||
op += decompressedSize;
|
||||
zds->dctx->expected = 0;
|
||||
zds->stage = zdss_init;
|
||||
someMoreWork = 0;
|
||||
break;
|
||||
} }
|
||||
/* check for single-pass mode opportunity */
|
||||
if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
|
||||
&& (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
|
||||
size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart);
|
||||
if (cSize <= (size_t)(iend-istart)) {
|
||||
size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, zds->ddict);
|
||||
if (ZSTD_isError(decompressedSize)) return decompressedSize;
|
||||
ip = istart + cSize;
|
||||
op += decompressedSize;
|
||||
zds->expected = 0;
|
||||
zds->streamStage = zdss_init;
|
||||
someMoreWork = 0;
|
||||
break;
|
||||
} }
|
||||
|
||||
/* Consume header */
|
||||
CHECK_F(ZSTD_decompressBegin_usingDDict(zds->dctx, zds->ddict));
|
||||
{ size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
|
||||
CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
|
||||
{ size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
|
||||
CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer+h1Size, h2Size));
|
||||
} }
|
||||
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
||||
DEBUGLOG(5, "Consume header");
|
||||
CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict));
|
||||
|
||||
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
||||
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
|
||||
if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
|
||||
zds->expected = MEM_readLE32(zds->headerBuffer + 4);
|
||||
zds->stage = ZSTDds_skipFrame;
|
||||
} else {
|
||||
CHECK_F(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize));
|
||||
zds->expected = ZSTD_blockHeaderSize;
|
||||
zds->stage = ZSTDds_decodeBlockHeader;
|
||||
}
|
||||
|
||||
/* Adapt buffer sizes to frame header instructions */
|
||||
{ size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
|
||||
size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
|
||||
zds->blockSize = blockSize;
|
||||
if (zds->inBuffSize < blockSize) {
|
||||
/* control buffer memory usage */
|
||||
DEBUGLOG(5, "Control max buffer memory usage");
|
||||
zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
|
||||
if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_windowTooLarge);
|
||||
|
||||
/* Adapt buffer sizes to frame header instructions */
|
||||
{ size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_MAX);
|
||||
size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
|
||||
zds->blockSize = blockSize;
|
||||
if ((zds->inBuffSize < blockSize) || (zds->outBuffSize < neededOutSize)) {
|
||||
size_t const bufferSize = blockSize + neededOutSize;
|
||||
DEBUGLOG(5, "inBuff : from %u to %u",
|
||||
(U32)zds->inBuffSize, (U32)blockSize);
|
||||
DEBUGLOG(5, "outBuff : from %u to %u",
|
||||
(U32)zds->outBuffSize, (U32)neededOutSize);
|
||||
if (zds->staticSize) { /* static DCtx */
|
||||
DEBUGLOG(5, "staticSize : %u", (U32)zds->staticSize);
|
||||
assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
|
||||
if (bufferSize > zds->staticSize - sizeof(ZSTD_DCtx))
|
||||
return ERROR(memory_allocation);
|
||||
} else {
|
||||
ZSTD_free(zds->inBuff, zds->customMem);
|
||||
zds->inBuffSize = 0;
|
||||
zds->inBuff = (char*)ZSTD_malloc(blockSize, zds->customMem);
|
||||
if (zds->inBuff == NULL) return ERROR(memory_allocation);
|
||||
zds->inBuffSize = blockSize;
|
||||
}
|
||||
if (zds->outBuffSize < neededOutSize) {
|
||||
ZSTD_free(zds->outBuff, zds->customMem);
|
||||
zds->outBuffSize = 0;
|
||||
zds->outBuff = (char*)ZSTD_malloc(neededOutSize, zds->customMem);
|
||||
if (zds->outBuff == NULL) return ERROR(memory_allocation);
|
||||
zds->outBuffSize = neededOutSize;
|
||||
} }
|
||||
zds->stage = zdss_read;
|
||||
}
|
||||
zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem);
|
||||
if (zds->inBuff == NULL) return ERROR(memory_allocation);
|
||||
}
|
||||
zds->inBuffSize = blockSize;
|
||||
zds->outBuff = zds->inBuff + zds->inBuffSize;
|
||||
zds->outBuffSize = neededOutSize;
|
||||
} }
|
||||
zds->streamStage = zdss_read;
|
||||
/* pass-through */
|
||||
|
||||
case zdss_read:
|
||||
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
|
||||
DEBUGLOG(5, "stage zdss_read");
|
||||
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
||||
DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
|
||||
if (neededInSize==0) { /* end of frame */
|
||||
zds->stage = zdss_init;
|
||||
zds->streamStage = zdss_init;
|
||||
someMoreWork = 0;
|
||||
break;
|
||||
}
|
||||
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
||||
const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
|
||||
size_t const decodedSize = ZSTD_decompressContinue(zds->dctx,
|
||||
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
||||
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
||||
zds->outBuff + zds->outStart, (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart),
|
||||
ip, neededInSize);
|
||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||
ip += neededInSize;
|
||||
if (!decodedSize && !isSkipFrame) break; /* this was just a header */
|
||||
zds->outEnd = zds->outStart + decodedSize;
|
||||
zds->stage = zdss_flush;
|
||||
zds->streamStage = zdss_flush;
|
||||
break;
|
||||
}
|
||||
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
||||
zds->stage = zdss_load;
|
||||
/* pass-through */
|
||||
}
|
||||
} }
|
||||
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
||||
zds->streamStage = zdss_load;
|
||||
/* pass-through */
|
||||
|
||||
case zdss_load:
|
||||
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
|
||||
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
|
||||
size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */
|
||||
size_t loadedSize;
|
||||
if (toLoad > zds->inBuffSize - zds->inPos) return ERROR(corruption_detected); /* should never happen */
|
||||
@@ -2337,17 +2392,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
||||
|
||||
/* decode loaded input */
|
||||
{ const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
|
||||
size_t const decodedSize = ZSTD_decompressContinue(zds->dctx,
|
||||
{ const int isSkipFrame = ZSTD_isSkipFrame(zds);
|
||||
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
||||
zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
|
||||
zds->inBuff, neededInSize);
|
||||
if (ZSTD_isError(decodedSize)) return decodedSize;
|
||||
zds->inPos = 0; /* input is consumed */
|
||||
if (!decodedSize && !isSkipFrame) { zds->stage = zdss_read; break; } /* this was just a header */
|
||||
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
||||
zds->outEnd = zds->outStart + decodedSize;
|
||||
zds->stage = zdss_flush;
|
||||
/* pass-through */
|
||||
} }
|
||||
zds->streamStage = zdss_flush;
|
||||
/* pass-through */
|
||||
|
||||
case zdss_flush:
|
||||
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
||||
@@ -2355,37 +2410,41 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
||||
op += flushedSize;
|
||||
zds->outStart += flushedSize;
|
||||
if (flushedSize == toFlushSize) { /* flush completed */
|
||||
zds->stage = zdss_read;
|
||||
zds->streamStage = zdss_read;
|
||||
if (zds->outStart + zds->blockSize > zds->outBuffSize)
|
||||
zds->outStart = zds->outEnd = 0;
|
||||
break;
|
||||
}
|
||||
/* cannot complete flush */
|
||||
someMoreWork = 0;
|
||||
break;
|
||||
}
|
||||
} }
|
||||
/* cannot complete flush */
|
||||
someMoreWork = 0;
|
||||
break;
|
||||
|
||||
default: return ERROR(GENERIC); /* impossible */
|
||||
} }
|
||||
|
||||
/* result */
|
||||
input->pos += (size_t)(ip-istart);
|
||||
output->pos += (size_t)(op-ostart);
|
||||
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx);
|
||||
{ size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
|
||||
if (!nextSrcSizeHint) { /* frame fully decoded */
|
||||
if (zds->outEnd == zds->outStart) { /* output fully flushed */
|
||||
if (zds->hostageByte) {
|
||||
if (input->pos >= input->size) { zds->stage = zdss_read; return 1; } /* can't release hostage (not present) */
|
||||
if (input->pos >= input->size) {
|
||||
/* can't release hostage (not present) */
|
||||
zds->streamStage = zdss_read;
|
||||
return 1;
|
||||
}
|
||||
input->pos++; /* release hostage */
|
||||
}
|
||||
} /* zds->hostageByte */
|
||||
return 0;
|
||||
}
|
||||
} /* zds->outEnd == zds->outStart */
|
||||
if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
|
||||
input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
|
||||
zds->hostageByte=1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */
|
||||
} /* nextSrcSizeHint==0 */
|
||||
nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
|
||||
if (zds->inPos > nextSrcSizeHint) return ERROR(GENERIC); /* should never happen */
|
||||
nextSrcSizeHint -= zds->inPos; /* already loaded*/
|
||||
return nextSrcSizeHint;
|
||||
|
||||
@@ -576,7 +576,7 @@ typedef struct
|
||||
{
|
||||
ZSTD_CCtx* ref;
|
||||
ZSTD_CCtx* zc;
|
||||
void* workPlace; /* must be ZSTD_BLOCKSIZE_ABSOLUTEMAX allocated */
|
||||
void* workPlace; /* must be ZSTD_BLOCKSIZE_MAX allocated */
|
||||
} EStats_ress_t;
|
||||
|
||||
#define MAXREPOFFSET 1024
|
||||
@@ -585,14 +585,14 @@ static void ZDICT_countEStats(EStats_ress_t esr, ZSTD_parameters params,
|
||||
U32* countLit, U32* offsetcodeCount, U32* matchlengthCount, U32* litlengthCount, U32* repOffsets,
|
||||
const void* src, size_t srcSize, U32 notificationLevel)
|
||||
{
|
||||
size_t const blockSizeMax = MIN (ZSTD_BLOCKSIZE_ABSOLUTEMAX, 1 << params.cParams.windowLog);
|
||||
size_t const blockSizeMax = MIN (ZSTD_BLOCKSIZE_MAX, 1 << params.cParams.windowLog);
|
||||
size_t cSize;
|
||||
|
||||
if (srcSize > blockSizeMax) srcSize = blockSizeMax; /* protection vs large samples */
|
||||
{ size_t const errorCode = ZSTD_copyCCtx(esr.zc, esr.ref, 0);
|
||||
if (ZSTD_isError(errorCode)) { DISPLAYLEVEL(1, "warning : ZSTD_copyCCtx failed \n"); return; }
|
||||
}
|
||||
cSize = ZSTD_compressBlock(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_ABSOLUTEMAX, src, srcSize);
|
||||
cSize = ZSTD_compressBlock(esr.zc, esr.workPlace, ZSTD_BLOCKSIZE_MAX, src, srcSize);
|
||||
if (ZSTD_isError(cSize)) { DISPLAYLEVEL(3, "warning : could not compress sample size %u \n", (U32)srcSize); return; }
|
||||
|
||||
if (cSize) { /* if == 0; block is not compressible */
|
||||
@@ -700,7 +700,7 @@ static size_t ZDICT_analyzeEntropy(void* dstBuffer, size_t maxDstSize,
|
||||
/* init */
|
||||
esr.ref = ZSTD_createCCtx();
|
||||
esr.zc = ZSTD_createCCtx();
|
||||
esr.workPlace = malloc(ZSTD_BLOCKSIZE_ABSOLUTEMAX);
|
||||
esr.workPlace = malloc(ZSTD_BLOCKSIZE_MAX);
|
||||
if (!esr.ref || !esr.zc || !esr.workPlace) {
|
||||
eSize = ERROR(memory_allocation);
|
||||
DISPLAYLEVEL(1, "Not enough memory \n");
|
||||
|
||||
+376
-72
@@ -38,20 +38,21 @@ extern "C" {
|
||||
/*******************************************************************************************************
|
||||
Introduction
|
||||
|
||||
zstd, short for Zstandard, is a fast lossless compression algorithm, targeting real-time compression scenarios
|
||||
at zlib-level and better compression ratios. The zstd compression library provides in-memory compression and
|
||||
decompression functions. The library supports compression levels from 1 up to ZSTD_maxCLevel() which is 22.
|
||||
zstd, short for Zstandard, is a fast lossless compression algorithm,
|
||||
targeting real-time compression scenarios at zlib-level and better compression ratios.
|
||||
The zstd compression library provides in-memory compression and decompression functions.
|
||||
The library supports compression levels from 1 up to ZSTD_maxCLevel() which is currently 22.
|
||||
Levels >= 20, labeled `--ultra`, should be used with caution, as they require more memory.
|
||||
Compression can be done in:
|
||||
- a single step (described as Simple API)
|
||||
- a single step, reusing a context (described as Explicit memory management)
|
||||
- unbounded multiple steps (described as Streaming compression)
|
||||
The compression ratio achievable on small data can be highly improved using compression with a dictionary in:
|
||||
The compression ratio achievable on small data can be highly improved using a dictionary in:
|
||||
- a single step (described as Simple dictionary API)
|
||||
- a single step, reusing a dictionary (described as Fast dictionary API)
|
||||
|
||||
Advanced experimental functions can be accessed using #define ZSTD_STATIC_LINKING_ONLY before including zstd.h.
|
||||
These APIs shall never be used with a dynamic library.
|
||||
Advanced experimental APIs shall never be used with a dynamic library.
|
||||
They are not "stable", their definition may change in the future. Only static linking is allowed.
|
||||
*********************************************************************************************************/
|
||||
|
||||
@@ -61,13 +62,13 @@ extern "C" {
|
||||
#define ZSTD_VERSION_RELEASE 0
|
||||
|
||||
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
|
||||
ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to be used when checking dll version */
|
||||
ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< useful to check dll version */
|
||||
|
||||
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
|
||||
#define ZSTD_QUOTE(str) #str
|
||||
#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)
|
||||
#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
|
||||
ZSTDLIB_API const char* ZSTD_versionString(void);
|
||||
ZSTDLIB_API const char* ZSTD_versionString(void); /* >= v1.3.0 */
|
||||
|
||||
|
||||
/***************************************
|
||||
@@ -84,7 +85,7 @@ ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
|
||||
|
||||
/*! ZSTD_decompress() :
|
||||
* `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.
|
||||
* `dstCapacity` is an upper bound of originalSize.
|
||||
* `dstCapacity` is an upper bound of originalSize to regenerate.
|
||||
* If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data.
|
||||
* @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
|
||||
* or an errorCode if it fails (which can be tested using ZSTD_isError()). */
|
||||
@@ -92,21 +93,17 @@ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
|
||||
const void* src, size_t compressedSize);
|
||||
|
||||
/*! ZSTD_getDecompressedSize() :
|
||||
* NOTE: This function is planned to be obsolete, in favour of ZSTD_getFrameContentSize.
|
||||
* ZSTD_getFrameContentSize functions the same way, returning the decompressed size of a single
|
||||
* frame, but distinguishes empty frames from frames with an unknown size, or errors.
|
||||
*
|
||||
* Additionally, ZSTD_findDecompressedSize can be used instead. It can handle multiple
|
||||
* concatenated frames in one buffer, and so is more general.
|
||||
* As a result however, it requires more computation and entire frames to be passed to it,
|
||||
* as opposed to ZSTD_getFrameContentSize which requires only a single frame's header.
|
||||
* NOTE: This function is planned to be obsolete, in favor of ZSTD_getFrameContentSize().
|
||||
* ZSTD_getFrameContentSize() works the same way,
|
||||
* returning the decompressed size of a single frame,
|
||||
* but distinguishes empty frames from frames with an unknown size, or errors.
|
||||
*
|
||||
* 'src' is the start of a zstd compressed frame.
|
||||
* @return : content size to be decompressed, as a 64-bits value _if known_, 0 otherwise.
|
||||
* note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.
|
||||
* note 1 : decompressed size is an optional field, it may not be present, typically in streaming mode.
|
||||
* When `return==0`, data to decompress could be any size.
|
||||
* In which case, it's necessary to use streaming mode to decompress data.
|
||||
* Optionally, application can still use ZSTD_decompress() while relying on implied limits.
|
||||
* Optionally, application can use ZSTD_decompress() while relying on implied limits.
|
||||
* (For example, data may be necessarily cut into blocks <= 16 KB).
|
||||
* note 2 : decompressed size is always present when compression is done with ZSTD_compress()
|
||||
* note 3 : decompressed size can be very large (64-bits value),
|
||||
@@ -115,7 +112,7 @@ ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
|
||||
* note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.
|
||||
* Always ensure result fits within application's authorized limits.
|
||||
* Each application can set its own limits.
|
||||
* note 5 : when `return==0`, if precise failure cause is needed, use ZSTD_getFrameParams() to know more. */
|
||||
* note 5 : when `return==0`, if precise failure cause is needed, use ZSTD_getFrameHeader() to know more. */
|
||||
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
|
||||
|
||||
|
||||
@@ -140,29 +137,35 @@ ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
|
||||
|
||||
/*! ZSTD_compressCCtx() :
|
||||
* Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). */
|
||||
ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel);
|
||||
ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
int compressionLevel);
|
||||
|
||||
/*= Decompression context
|
||||
* When decompressing many times,
|
||||
* it is recommended to allocate a context just once, and re-use it for each successive compression operation.
|
||||
* it is recommended to allocate a context only once,
|
||||
* and re-use it for each successive compression operation.
|
||||
* This will make workload friendlier for system's memory.
|
||||
* Use one context per thread for parallel execution in multi-threaded environments. */
|
||||
* Use one context per thread for parallel execution. */
|
||||
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
|
||||
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
|
||||
|
||||
/*! ZSTD_decompressDCtx() :
|
||||
* Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()). */
|
||||
ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
* Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()) */
|
||||
ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize);
|
||||
|
||||
|
||||
/**************************
|
||||
* Simple dictionary API
|
||||
***************************/
|
||||
/*! ZSTD_compress_usingDict() :
|
||||
* Compression using a predefined Dictionary (see dictBuilder/zdict.h).
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
* Compression using a predefined Dictionary (see dictBuilder/zdict.h).
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
@@ -170,30 +173,31 @@ ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
|
||||
int compressionLevel);
|
||||
|
||||
/*! ZSTD_decompress_usingDict() :
|
||||
* Decompression using a predefined Dictionary (see dictBuilder/zdict.h).
|
||||
* Dictionary must be identical to the one used during compression.
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
* Decompression using a predefined Dictionary (see dictBuilder/zdict.h).
|
||||
* Dictionary must be identical to the one used during compression.
|
||||
* Note : This function loads the dictionary, resulting in significant startup delay.
|
||||
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
|
||||
ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
const void* dict,size_t dictSize);
|
||||
|
||||
|
||||
/****************************
|
||||
* Fast dictionary API
|
||||
****************************/
|
||||
/**********************************
|
||||
* Bulk processing dictionary API
|
||||
*********************************/
|
||||
typedef struct ZSTD_CDict_s ZSTD_CDict;
|
||||
|
||||
/*! ZSTD_createCDict() :
|
||||
* When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
|
||||
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
|
||||
* ZSTD_CDict can be created once and used by multiple threads concurrently, as its usage is read-only.
|
||||
* `dictBuffer` can be released after ZSTD_CDict creation, as its content is copied within CDict */
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||
* When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
|
||||
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
|
||||
* ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
|
||||
* `dictBuffer` can be released after ZSTD_CDict creation, since its content is copied within CDict */
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
|
||||
int compressionLevel);
|
||||
|
||||
/*! ZSTD_freeCDict() :
|
||||
* Function frees memory allocated by ZSTD_createCDict(). */
|
||||
* Function frees memory allocated by ZSTD_createCDict(). */
|
||||
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
|
||||
|
||||
/*! ZSTD_compress_usingCDict() :
|
||||
@@ -210,17 +214,17 @@ ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
|
||||
typedef struct ZSTD_DDict_s ZSTD_DDict;
|
||||
|
||||
/*! ZSTD_createDDict() :
|
||||
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
* dictBuffer can be released after DDict creation, as its content is copied inside DDict */
|
||||
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
* dictBuffer can be released after DDict creation, as its content is copied inside DDict */
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
|
||||
|
||||
/*! ZSTD_freeDDict() :
|
||||
* Function frees memory allocated with ZSTD_createDDict() */
|
||||
* Function frees memory allocated with ZSTD_createDDict() */
|
||||
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
|
||||
|
||||
/*! ZSTD_decompress_usingDDict() :
|
||||
* Decompression using a digested Dictionary.
|
||||
* Faster startup than ZSTD_decompress_usingDict(), recommended when same dictionary is used multiple times. */
|
||||
* Decompression using a digested Dictionary.
|
||||
* Faster startup than ZSTD_decompress_usingDict(), recommended when same dictionary is used multiple times. */
|
||||
ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
|
||||
void* dst, size_t dstCapacity,
|
||||
const void* src, size_t srcSize,
|
||||
@@ -277,15 +281,17 @@ typedef struct ZSTD_outBuffer_s {
|
||||
* ZSTD_endStream() instructs to finish a frame.
|
||||
* It will perform a flush and write frame epilogue.
|
||||
* The epilogue is required for decoders to consider a frame completed.
|
||||
* Similar to ZSTD_flushStream(), it may not be able to flush the full content if `output->size` is too small.
|
||||
* ZSTD_endStream() may not be able to flush full data if `output->size` is too small.
|
||||
* In which case, call again ZSTD_endStream() to complete the flush.
|
||||
* @return : nb of bytes still present within internal buffer (0 if it's empty, hence compression completed)
|
||||
* @return : 0 if frame fully completed and fully flushed,
|
||||
or >0 if some data is still present within internal buffer
|
||||
(value is minimum size estimation for remaining data to flush, but it could be more)
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
*
|
||||
* *******************************************************************/
|
||||
|
||||
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are effectively same object */
|
||||
/* Continue due distinghish them for compatibility with versions <= v1.2.0 */
|
||||
typedef ZSTD_CCtx ZSTD_CStream; /**< CCtx and CStream are now effectively same object (>= v1.3.0) */
|
||||
/* But continue to distinguish them for compatibility with versions <= v1.2.0 */
|
||||
/*===== ZSTD_CStream management functions =====*/
|
||||
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
|
||||
@@ -323,7 +329,8 @@ ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output
|
||||
* The return value is a suggested next input size (a hint to improve latency) that will never load more than the current frame.
|
||||
* *******************************************************************************/
|
||||
|
||||
typedef struct ZSTD_DStream_s ZSTD_DStream;
|
||||
typedef ZSTD_DCtx ZSTD_DStream; /**< DCtx and DStream are now effectively same object (>= v1.3.0) */
|
||||
/* But continue to distinguish them for compatibility with versions <= v1.2.0 */
|
||||
/*===== ZSTD_DStream management functions =====*/
|
||||
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
|
||||
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
|
||||
@@ -338,8 +345,6 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
|
||||
#endif /* ZSTD_H_235446 */
|
||||
|
||||
|
||||
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
|
||||
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
|
||||
|
||||
/****************************************************************************************
|
||||
* START OF ADVANCED AND EXPERIMENTAL FUNCTIONS
|
||||
@@ -349,6 +354,9 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output
|
||||
* Use them only in association with static linking.
|
||||
* ***************************************************************************************/
|
||||
|
||||
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
|
||||
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
|
||||
|
||||
/* --- Constants ---*/
|
||||
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */
|
||||
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
|
||||
@@ -378,7 +386,8 @@ static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable f
|
||||
|
||||
|
||||
/*--- Advanced types ---*/
|
||||
typedef enum { ZSTD_fast, ZSTD_dfast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2, ZSTD_btopt, ZSTD_btultra } ZSTD_strategy; /* from faster to stronger */
|
||||
typedef enum { ZSTD_fast=1, ZSTD_dfast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2,
|
||||
ZSTD_btlazy2, ZSTD_btopt, ZSTD_btultra } ZSTD_strategy; /* from faster to stronger */
|
||||
|
||||
typedef struct {
|
||||
unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */
|
||||
@@ -412,6 +421,9 @@ typedef struct {
|
||||
typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
|
||||
typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
|
||||
typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
|
||||
/* use this constant to defer to stdlib's functions */
|
||||
static const ZSTD_customMem ZSTD_defaultCMem = { NULL, NULL, NULL };
|
||||
|
||||
|
||||
/***************************************
|
||||
* Frame size functions
|
||||
@@ -485,21 +497,22 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
|
||||
* These functions make it possible to estimate memory usage
|
||||
* of a future target object, before its allocation,
|
||||
* given a set of parameters, which vary depending on target object.
|
||||
* The objective is to guide decision before allocation. */
|
||||
* The objective is to guide decision before allocation.
|
||||
* Note : CCtx estimation is only correct for single-threaded compression */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
|
||||
|
||||
/*! ZSTD_estimate?StreamSize() :
|
||||
* Note : if streaming is init with function ZSTD_init?Stream_usingDict(),
|
||||
* an internal ?Dict will be created, which size is not estimated.
|
||||
* In this case, get additional size by using ZSTD_estimate?DictSize */
|
||||
* an internal ?Dict will be created, which size is not estimated here.
|
||||
* In this case, get total size by adding ZSTD_estimate?DictSize */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCStreamSize(ZSTD_compressionParameters cParams);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDStreamSize(ZSTD_frameHeader fHeader);
|
||||
|
||||
/*! ZSTD_estimate?DictSize() :
|
||||
* Note : if dictionary is created "byReference", reduce estimation by dictSize */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize);
|
||||
* Note : dictionary created "byReference" are smaller */
|
||||
ZSTDLIB_API size_t ZSTD_estimateCDictSize(ZSTD_compressionParameters cParams, size_t dictSize, unsigned byReference);
|
||||
ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, unsigned byReference);
|
||||
|
||||
|
||||
/***************************************
|
||||
@@ -509,6 +522,25 @@ ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize);
|
||||
* Create a ZSTD compression context using external alloc and free functions */
|
||||
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
|
||||
|
||||
/*! ZSTD_initStaticCCtx() : initialize a fixed-size zstd compression context
|
||||
* workspace: The memory area to emplace the context into.
|
||||
* Provided pointer must 8-bytes aligned.
|
||||
* It must outlive context usage.
|
||||
* workspaceSize: Use ZSTD_estimateCCtxSize() or ZSTD_estimateCStreamSize()
|
||||
* to determine how large workspace must be to support scenario.
|
||||
* @return : pointer to ZSTD_CCtx*, or NULL if error (size too small)
|
||||
* Note : zstd will never resize nor malloc() when using a static cctx.
|
||||
* If it needs more memory than available, it will simply error out.
|
||||
* Note 2 : there is no corresponding "free" function.
|
||||
* Since workspace was allocated externally, it must be freed externally too.
|
||||
* Limitation 1 : currently not compatible with internal CDict creation, such as
|
||||
* ZSTD_CCtx_loadDictionary() or ZSTD_initCStream_usingDict().
|
||||
* Limitation 2 : currently not compatible with multi-threading
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
|
||||
|
||||
|
||||
/* !!! To be deprecated !!! */
|
||||
typedef enum {
|
||||
ZSTD_p_forceWindow, /* Force back-references to remain < windowSize, even when referencing Dictionary content (default:0) */
|
||||
ZSTD_p_forceRawDict /* Force loading dictionary in "content-only" mode (no header analysis) */
|
||||
@@ -518,17 +550,40 @@ typedef enum {
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()) */
|
||||
ZSTDLIB_API size_t ZSTD_setCCtxParameter(ZSTD_CCtx* cctx, ZSTD_CCtxParameter param, unsigned value);
|
||||
|
||||
|
||||
/*! ZSTD_createCDict_byReference() :
|
||||
* Create a digested dictionary for compression
|
||||
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
|
||||
* It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
|
||||
|
||||
|
||||
typedef enum { ZSTD_dm_auto=0, ZSTD_dm_rawContent, ZSTD_dm_fullDict } ZSTD_dictMode_e;
|
||||
/*! ZSTD_createCDict_advanced() :
|
||||
* Create a ZSTD_CDict using external alloc and free, and customized compression parameters */
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, unsigned byReference,
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
|
||||
unsigned byReference, ZSTD_dictMode_e dictMode,
|
||||
ZSTD_compressionParameters cParams, ZSTD_customMem customMem);
|
||||
|
||||
/*! ZSTD_initStaticCDict_advanced() :
|
||||
* Generate a digested dictionary in provided memory area.
|
||||
* workspace: The memory area to emplace the dictionary into.
|
||||
* Provided pointer must 8-bytes aligned.
|
||||
* It must outlive dictionary usage.
|
||||
* workspaceSize: Use ZSTD_estimateCDictSize()
|
||||
* to determine how large workspace must be.
|
||||
* cParams : use ZSTD_getCParams() to transform a compression level
|
||||
* into its relevants cParams.
|
||||
* @return : pointer to ZSTD_CDict*, or NULL if error (size too small)
|
||||
* Note : there is no corresponding "free" function.
|
||||
* Since workspace was allocated externally, it must be freed externally.
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_CDict* ZSTD_initStaticCDict(
|
||||
void* workspace, size_t workspaceSize,
|
||||
const void* dict, size_t dictSize,
|
||||
unsigned byReference, ZSTD_dictMode_e dictMode,
|
||||
ZSTD_compressionParameters cParams);
|
||||
|
||||
/*! ZSTD_getCParams() :
|
||||
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
|
||||
* `estimatedSrcSize` value is optional, select 0 if not known */
|
||||
@@ -544,8 +599,8 @@ ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long l
|
||||
ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
|
||||
|
||||
/*! ZSTD_adjustCParams() :
|
||||
* optimize params for a given `srcSize` and `dictSize`.
|
||||
* both values are optional, select `0` if unknown. */
|
||||
* optimize params for a given `srcSize` and `dictSize`.
|
||||
* both values are optional, select `0` if unknown. */
|
||||
ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
|
||||
|
||||
/*! ZSTD_compress_advanced() :
|
||||
@@ -577,10 +632,28 @@ ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
|
||||
* Create a ZSTD decompression context using external alloc and free functions */
|
||||
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
|
||||
|
||||
/*! ZSTD_initStaticDCtx() : initialize a fixed-size zstd decompression context
|
||||
* workspace: The memory area to emplace the context into.
|
||||
* Provided pointer must 8-bytes aligned.
|
||||
* It must outlive context usage.
|
||||
* workspaceSize: Use ZSTD_estimateDCtxSize() or ZSTD_estimateDStreamSize()
|
||||
* to determine how large workspace must be to support scenario.
|
||||
* @return : pointer to ZSTD_DCtx*, or NULL if error (size too small)
|
||||
* Note : zstd will never resize nor malloc() when using a static dctx.
|
||||
* If it needs more memory than available, it will simply error out.
|
||||
* Note 2 : static dctx is incompatible with legacy support
|
||||
* Note 3 : there is no corresponding "free" function.
|
||||
* Since workspace was allocated externally, it must be freed externally.
|
||||
* Limitation : currently not compatible with internal DDict creation,
|
||||
* such as ZSTD_initDStream_usingDict().
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
|
||||
|
||||
/*! ZSTD_createDDict_byReference() :
|
||||
* Create a digested dictionary, ready to start decompression operation without startup delay.
|
||||
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
|
||||
* It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */
|
||||
* Dictionary content is referenced, and therefore stays in dictBuffer.
|
||||
* It is important that dictBuffer outlives DDict,
|
||||
* it must remain read accessible throughout the lifetime of DDict */
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
|
||||
|
||||
/*! ZSTD_createDDict_advanced() :
|
||||
@@ -588,6 +661,21 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, siz
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
|
||||
unsigned byReference, ZSTD_customMem customMem);
|
||||
|
||||
/*! ZSTD_initStaticDDict() :
|
||||
* Generate a digested dictionary in provided memory area.
|
||||
* workspace: The memory area to emplace the dictionary into.
|
||||
* Provided pointer must 8-bytes aligned.
|
||||
* It must outlive dictionary usage.
|
||||
* workspaceSize: Use ZSTD_estimateDDictSize()
|
||||
* to determine how large workspace must be.
|
||||
* @return : pointer to ZSTD_DDict*, or NULL if error (size too small)
|
||||
* Note : there is no corresponding "free" function.
|
||||
* Since workspace was allocated externally, it must be freed externally.
|
||||
*/
|
||||
ZSTDLIB_API ZSTD_DDict* ZSTD_initStaticDDict(void* workspace, size_t workspaceSize,
|
||||
const void* dict, size_t dictSize,
|
||||
unsigned byReference);
|
||||
|
||||
/*! ZSTD_getDictID_fromDict() :
|
||||
* Provides the dictID stored within dictionary.
|
||||
* if @return == 0, the dictionary is not conformant with Zstandard specification.
|
||||
@@ -609,7 +697,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
|
||||
* Note : this use case also happens when using a non-conformant dictionary.
|
||||
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
|
||||
* - This is not a Zstandard frame.
|
||||
* When identifying the exact failure cause, it's possible to use ZSTD_getFrameParams(), which will provide a more precise error code. */
|
||||
* When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
|
||||
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
|
||||
|
||||
@@ -620,11 +708,11 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
|
||||
/*===== Advanced Streaming compression functions =====*/
|
||||
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct, a size of 0 means unknown. for a frame size of 0 use initCStream_advanced */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< note: a dict will not be used if dict == NULL or dictSize < 8. This result in the creation of an internal CDict */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
|
||||
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be 0 (meaning unknown). note: if the contentSizeFlag is set, pledgedSrcSize == 0 means the source size is actually 0 */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, unsigned long long pledgedSrcSize, ZSTD_frameParameters fParams); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
|
||||
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs, const ZSTD_CDict* cdict, ZSTD_frameParameters fParams, unsigned long long pledgedSrcSize); /**< same as ZSTD_initCStream_usingCDict(), with control over frame parameters */
|
||||
|
||||
/*! ZSTD_resetCStream() :
|
||||
* start a new compression job, using same parameters from previous job.
|
||||
@@ -704,7 +792,7 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci
|
||||
Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
|
||||
A ZSTD_DCtx object can be re-used multiple times.
|
||||
|
||||
First typical operation is to retrieve frame parameters, using ZSTD_getFrameParams().
|
||||
First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().
|
||||
It fills a ZSTD_frameParams structure which provide important information to correctly decode the frame,
|
||||
such as the minimum rolling buffer size to allocate to decompress data (`windowSize`),
|
||||
and the dictionary ID used.
|
||||
@@ -751,7 +839,7 @@ ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapaci
|
||||
b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
|
||||
c) Frame Content - any content (User Data) of length equal to Frame Size
|
||||
For skippable frames ZSTD_decompressContinue() always returns 0.
|
||||
For skippable frames ZSTD_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable.
|
||||
For skippable frames ZSTD_getFrameHeader() returns fparamsPtr->windowLog==0 what means that a frame is skippable.
|
||||
Note : If fparamsPtr->frameContentSize==0, it is ambiguous: the frame might actually be a Zstd encoded frame with no content.
|
||||
For purposes of decompression, it is valid in both cases to skip the frame using
|
||||
ZSTD_findFrameCompressedSize to find its size in bytes.
|
||||
@@ -770,6 +858,221 @@ ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t ds
|
||||
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
|
||||
ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
|
||||
|
||||
|
||||
|
||||
/*=== New advanced API (experimental, and compression only) ===*/
|
||||
|
||||
/* notes on API design :
|
||||
* In this proposal, parameters are pushed one by one into an existing CCtx,
|
||||
* and then applied on all subsequent compression jobs.
|
||||
* When no parameter is ever provided, CCtx is created with compression level ZSTD_CLEVEL_DEFAULT.
|
||||
*
|
||||
* This API is intended to replace all others experimental API.
|
||||
* It can basically do all other use cases, and even new ones.
|
||||
* It stands a good chance to become "stable",
|
||||
* after a reasonable testing period.
|
||||
*/
|
||||
|
||||
/* note on naming convention :
|
||||
* Initially, the API favored names like ZSTD_setCCtxParameter() .
|
||||
* In this proposal, convention is changed towards ZSTD_CCtx_setParameter() .
|
||||
* The main driver is that it identifies more clearly the target object type.
|
||||
* It feels clearer in light of potential variants :
|
||||
* ZSTD_CDict_setParameter() (rather than ZSTD_setCDictParameter())
|
||||
* ZSTD_DCtx_setParameter() (rather than ZSTD_setDCtxParameter() )
|
||||
* Left variant feels easier to distinguish.
|
||||
*/
|
||||
|
||||
/* note on enum design :
|
||||
* All enum will be manually set to explicit values before reaching "stable API" status */
|
||||
|
||||
typedef enum {
|
||||
/* compression parameters */
|
||||
ZSTD_p_compressionLevel=100, /* Update all compression parameters according to pre-defined cLevel table
|
||||
* Default level is ZSTD_CLEVEL_DEFAULT==3.
|
||||
* Special: value 0 means "do not change cLevel". */
|
||||
ZSTD_p_windowLog, /* Maximum allowed back-reference distance, expressed as power of 2.
|
||||
* Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.
|
||||
* Special: value 0 means "do not change windowLog". */
|
||||
ZSTD_p_hashLog, /* Size of the probe table, as a power of 2.
|
||||
* Resulting table size is (1 << (hashLog+2)).
|
||||
* Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.
|
||||
* Larger tables improve compression ratio of strategies <= dFast,
|
||||
* and improve speed of strategies > dFast.
|
||||
* Special: value 0 means "do not change hashLog". */
|
||||
ZSTD_p_chainLog, /* Size of the full-search table, as a power of 2.
|
||||
* Resulting table size is (1 << (chainLog+2)).
|
||||
* Larger tables result in better and slower compression.
|
||||
* This parameter is useless when using "fast" strategy.
|
||||
* Special: value 0 means "do not change chainLog". */
|
||||
ZSTD_p_searchLog, /* Number of search attempts, as a power of 2.
|
||||
* More attempts result in better and slower compression.
|
||||
* This parameter is useless when using "fast" and "dFast" strategies.
|
||||
* Special: value 0 means "do not change searchLog". */
|
||||
ZSTD_p_minMatch, /* Minimum size of searched matches (note : repCode matches can be smaller).
|
||||
* Larger values make faster compression and decompression, but decrease ratio.
|
||||
* Must be clamped between ZSTD_SEARCHLENGTH_MIN and ZSTD_SEARCHLENGTH_MAX.
|
||||
* Note that currently, for all strategies < btopt, effective minimum is 4.
|
||||
* Note that currently, for all strategies > fast, effective maximum is 6.
|
||||
* Special: value 0 means "do not change minMatchLength". */
|
||||
ZSTD_p_targetLength, /* Only useful for strategies >= btopt.
|
||||
* Length of Match considered "good enough" to stop search.
|
||||
* Larger values make compression stronger and slower.
|
||||
* Special: value 0 means "do not change targetLength". */
|
||||
ZSTD_p_compressionStrategy, /* See ZSTD_strategy enum definition.
|
||||
* Cast selected strategy as unsigned for ZSTD_CCtx_setParameter() compatibility.
|
||||
* The higher the value of selected strategy, the more complex it is,
|
||||
* resulting in stronger and slower compression.
|
||||
* Special: value 0 means "do not change strategy". */
|
||||
#if 0
|
||||
ZSTD_p_windowSize, /* Maximum allowed back-reference distance.
|
||||
* Can be set to a more precise value than windowLog.
|
||||
* Will be transparently reduced to closest possible inferior value
|
||||
* (see Zstandard compression format) */
|
||||
/* Not ready yet ! */
|
||||
#endif
|
||||
|
||||
/* frame parameters */
|
||||
ZSTD_p_contentSizeFlag=200, /* Content size is written into frame header _whenever known_ (default:1) */
|
||||
ZSTD_p_checksumFlag, /* A 32-bits checksum of content is written at end of frame (default:0) */
|
||||
ZSTD_p_dictIDFlag, /* When applicable, dictID of dictionary is provided in frame header (default:1) */
|
||||
|
||||
/* dictionary parameters */
|
||||
ZSTD_p_refDictContent=300, /* Content of dictionary content will be referenced, instead of copied (default:0).
|
||||
* This avoids duplicating dictionary content.
|
||||
* But it also requires that dictionary buffer outlives its users */
|
||||
/* Not ready yet ! <=================================== */
|
||||
ZSTD_p_dictMode, /* Select how dictionary must be interpreted. Value must be from type ZSTD_dictMode_e.
|
||||
* default : 0==auto : dictionary will be "full" if it respects specification, otherwise it will be "rawContent" */
|
||||
|
||||
/* multi-threading parameters */
|
||||
ZSTD_p_nbThreads=400, /* Select how many threads a compression job can spawn (default:1)
|
||||
* More threads improve speed, but also increase memory usage.
|
||||
* Can only receive a value > 1 if ZSTD_MULTITHREAD is enabled.
|
||||
* Special: value 0 means "do not change nbThreads" */
|
||||
ZSTD_p_jobSize, /* Size of a compression job. Each compression job is completed in parallel.
|
||||
* 0 means default, which is dynamically determined based on compression parameters.
|
||||
* Job size must be a minimum of overlapSize, or 1 KB, whichever is largest
|
||||
* The minimum size is automatically and transparently enforced */
|
||||
ZSTD_p_overlapSizeLog, /* Size of previous input reloaded at the beginning of each job.
|
||||
* 0 => no overlap, 6(default) => use 1/8th of windowSize, >=9 => use full windowSize */
|
||||
|
||||
/* advanced parameters - may not remain available after API update */
|
||||
ZSTD_p_forceMaxWindow=1100, /* Force back-references to remain < windowSize,
|
||||
* even when referencing into Dictionary content.
|
||||
* default : 0 when using a CDict, 1 when using a Prefix */
|
||||
} ZSTD_cParameter;
|
||||
|
||||
|
||||
/*! ZSTD_CCtx_setParameter() :
|
||||
* Set one compression parameter, selected by enum ZSTD_cParameter.
|
||||
* Note : when `value` is an enum, cast it to unsigned for proper type checking.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()). */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, unsigned value);
|
||||
|
||||
/*! ZSTD_CCtx_setPledgedSrcSize() :
|
||||
* Total input data size to be compressed as a single frame.
|
||||
* This value will be controlled at the end, and result in error if not respected.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
* Note 1 : 0 means zero, empty.
|
||||
* In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN.
|
||||
* Note that ZSTD_CONTENTSIZE_UNKNOWN is default value for new compression jobs.
|
||||
* Note 2 : If all data is provided and consumed in a single round,
|
||||
* this value is overriden by srcSize instead. */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
|
||||
|
||||
/*! ZSTD_CCtx_loadDictionary() :
|
||||
* Create an internal CDict from dict buffer.
|
||||
* Decompression will have to use same buffer.
|
||||
* @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".
|
||||
* Note 1 : Dictionary content will be copied internally,
|
||||
* except if ZSTD_p_refDictContent is set.
|
||||
* Note 2 : Loading a dictionary involves building tables, which are dependent on compression parameters.
|
||||
* For this reason, compression parameters cannot be changed anymore after loading a dictionary.
|
||||
* It's also a CPU-heavy operation, with non-negligible impact on latency.
|
||||
* Note 3 : Dictionary will be used for all future compression jobs.
|
||||
* To return to "no-dictionary" situation, load a NULL dictionary */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
|
||||
|
||||
/*! ZSTD_CCtx_refCDict() :
|
||||
* Ref a prepared dictionary, to be used for all next compression jobs.
|
||||
* Note that compression parameters are enforced from within CDict,
|
||||
* and supercede any compression parameter previously set within CCtx.
|
||||
* The dictionary will remain valid for future compression jobs using same CCtx.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
* Special : adding a NULL CDict means "return to no-dictionary mode".
|
||||
* Note 1 : Currently, only one dictionary can be managed.
|
||||
* Adding a new dictionary effectively "discards" any previous one.
|
||||
* Note 2 : CDict is just referenced, its lifetime must outlive CCtx.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
|
||||
|
||||
/*! ZSTD_CCtx_refPrefix() :
|
||||
* Reference a prefix (content-only dictionary) to bootstrap next compression job.
|
||||
* Decompression will have to use same prefix.
|
||||
* Prefix is only used once. Tables are discarded at end of compression job.
|
||||
* If there is a need to use same prefix multiple times, consider embedding it into a ZSTD_CDict.
|
||||
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
|
||||
* Special : Adding a NULL (or 0-size) dictionary invalidates any previous prefix, meaning "return to no-dictionary mode".
|
||||
* Note 1 : Prefix buffer is referenced. It must outlive compression job.
|
||||
* Note 2 : Referencing a prefix involves building tables, which are dependent on compression parameters.
|
||||
* It's a CPU-heavy operation, with non-negligible impact on latency. */
|
||||
ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize); /* Not ready yet ! <===================================== */
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
ZSTD_e_continue=0, /* collect more data, encoder transparently decides when to output result, for optimal conditions */
|
||||
ZSTD_e_flush, /* flush any data provided so far - frame will continue, future data can still reference previous data for better compression */
|
||||
ZSTD_e_end /* flush any remaining data and ends current frame. Any future compression starts a new frame. */
|
||||
} ZSTD_EndDirective;
|
||||
|
||||
/*! ZSTD_compress_generic() :
|
||||
* Behave about the same as ZSTD_compressStream. To note :
|
||||
* - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_setParameter()
|
||||
* - Compression parameters cannot be changed once compression is started.
|
||||
* - *dstPos must be <= dstCapacity, *srcPos must be <= srcSize
|
||||
* - *dspPos and *srcPos will be updated. They are guaranteed to remain below their respective limit.
|
||||
* - @return provides the minimum amount of data still to flush from internal buffers
|
||||
* or an error code, which can be tested using ZSTD_isError().
|
||||
* if @return != 0, flush is not fully completed, there is some data left within internal buffers.
|
||||
* - after a ZSTD_e_end directive, if internal buffer is not fully flushed,
|
||||
* only ZSTD_e_end or ZSTD_e_flush operations are allowed.
|
||||
* It is necessary to fully flush internal buffers
|
||||
* before starting a new compression job, or changing compression parameters.
|
||||
*/
|
||||
ZSTDLIB_API size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
|
||||
ZSTD_outBuffer* output,
|
||||
ZSTD_inBuffer* input,
|
||||
ZSTD_EndDirective endOp);
|
||||
|
||||
/*! ZSTD_CCtx_reset() :
|
||||
* Return a CCtx to clean state.
|
||||
* Useful after an error, or to interrupt an ongoing compression job and start a new one.
|
||||
* Any internal data not yet flushed is cancelled.
|
||||
* Dictionary (if any) is dropped.
|
||||
* It's possible to modify compression parameters after a reset.
|
||||
*/
|
||||
ZSTDLIB_API void ZSTD_CCtx_reset(ZSTD_CCtx* cctx); /* Not ready yet ! */
|
||||
|
||||
|
||||
/*! ZSTD_compress_generic_simpleArgs() :
|
||||
* Same as ZSTD_compress_generic(),
|
||||
* but using only integral types as arguments.
|
||||
* Argument list is larger and less expressive than ZSTD_{in,out}Buffer,
|
||||
* but can be helpful for binders from dynamic languages
|
||||
* which have troubles handling structures containing memory pointers.
|
||||
*/
|
||||
size_t ZSTD_compress_generic_simpleArgs (
|
||||
ZSTD_CCtx* cctx,
|
||||
void* dst, size_t dstCapacity, size_t* dstPos,
|
||||
const void* src, size_t srcSize, size_t* srcPos,
|
||||
ZSTD_EndDirective endOp);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Block functions
|
||||
|
||||
@@ -784,7 +1087,7 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
|
||||
+ compression : any ZSTD_compressBegin*() variant, including with dictionary
|
||||
+ decompression : any ZSTD_decompressBegin*() variant, including with dictionary
|
||||
+ copyCCtx() and copyDCtx() can be used too
|
||||
- Block size is limited, it must be <= ZSTD_getBlockSizeMax() <= ZSTD_BLOCKSIZE_ABSOLUTEMAX
|
||||
- Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX
|
||||
+ If input is larger than a block size, it's necessary to split input data into multiple blocks
|
||||
+ For inputs larger than a single block size, consider using the regular ZSTD_compress() instead.
|
||||
Frame metadata is not that costly, and quickly becomes negligible as source size grows larger.
|
||||
@@ -797,9 +1100,10 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
|
||||
Use ZSTD_insertBlock() for such a case.
|
||||
*/
|
||||
|
||||
#define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */
|
||||
#define ZSTD_BLOCKSIZELOG_MAX 17
|
||||
#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX) /* define, for static allocation */
|
||||
/*===== Raw zstd block functions =====*/
|
||||
ZSTDLIB_API size_t ZSTD_getBlockSizeMax(ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
|
||||
ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
|
||||
ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */
|
||||
|
||||
Reference in New Issue
Block a user