[lib] Add ZSTD_d_stableOutBuffer
This commit is contained in:
parent
b104f8e3eb
commit
a4ff217baf
@ -47,6 +47,7 @@ const char* ERR_getErrorString(ERR_enum code)
|
|||||||
/* following error codes are not stable and may be removed or changed in a future version */
|
/* following error codes are not stable and may be removed or changed in a future version */
|
||||||
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
|
case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
|
||||||
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
|
case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
|
||||||
|
case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
|
||||||
case PREFIX(maxCode):
|
case PREFIX(maxCode):
|
||||||
default: return notErrorCode;
|
default: return notErrorCode;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ typedef enum {
|
|||||||
/* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
|
/* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
|
||||||
ZSTD_error_frameIndex_tooLarge = 100,
|
ZSTD_error_frameIndex_tooLarge = 100,
|
||||||
ZSTD_error_seekableIO = 102,
|
ZSTD_error_seekableIO = 102,
|
||||||
|
ZSTD_error_dstBuffer_wrong = 104,
|
||||||
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
|
ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
|
||||||
} ZSTD_ErrorCode;
|
} ZSTD_ErrorCode;
|
||||||
|
|
||||||
|
@ -113,6 +113,7 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
|
|||||||
dctx->noForwardProgress = 0;
|
dctx->noForwardProgress = 0;
|
||||||
dctx->oversizedDuration = 0;
|
dctx->oversizedDuration = 0;
|
||||||
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
|
||||||
|
dctx->outBufferMode = ZSTD_obm_buffered;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
|
||||||
@ -1402,6 +1403,10 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
|
|||||||
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
|
||||||
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
|
||||||
return bounds;
|
return bounds;
|
||||||
|
case ZSTD_d_stableOutBuffer:
|
||||||
|
bounds.lowerBound = (int)ZSTD_obm_buffered;
|
||||||
|
bounds.upperBound = (int)ZSTD_obm_stable;
|
||||||
|
return bounds;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
bounds.error = ERROR(parameter_unsupported);
|
bounds.error = ERROR(parameter_unsupported);
|
||||||
@ -1437,6 +1442,10 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
|
|||||||
CHECK_DBOUNDS(ZSTD_d_format, value);
|
CHECK_DBOUNDS(ZSTD_d_format, value);
|
||||||
dctx->format = (ZSTD_format_e)value;
|
dctx->format = (ZSTD_format_e)value;
|
||||||
return 0;
|
return 0;
|
||||||
|
case ZSTD_d_stableOutBuffer:
|
||||||
|
CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
|
||||||
|
dctx->outBufferMode = (ZSTD_outBufferMode_e)value;
|
||||||
|
return 0;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
RETURN_ERROR(parameter_unsupported);
|
RETURN_ERROR(parameter_unsupported);
|
||||||
@ -1517,6 +1526,50 @@ static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
|
|||||||
return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
|
return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
|
||||||
|
{
|
||||||
|
ZSTD_outBuffer const expect = zds->expectedOutBuffer;
|
||||||
|
/* No requirement when ZSTD_obm_stable is not enabled. */
|
||||||
|
if (zds->outBufferMode != ZSTD_obm_stable)
|
||||||
|
return 0;
|
||||||
|
/* Any buffer is allowed in zdss_init, this must be the same for every other call until
|
||||||
|
* the context is reset.
|
||||||
|
*/
|
||||||
|
if (zds->streamStage == zdss_init)
|
||||||
|
return 0;
|
||||||
|
/* The buffer must match our expectation exactly. */
|
||||||
|
if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
|
||||||
|
return 0;
|
||||||
|
RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!");
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ZSTD_decompressContinueStream(
|
||||||
|
ZSTD_DStream* zds, char** op, char* oend,
|
||||||
|
void const* src, size_t srcSize) {
|
||||||
|
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
||||||
|
if (zds->outBufferMode == ZSTD_obm_buffered) {
|
||||||
|
size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
|
||||||
|
size_t const decodedSize = ZSTD_decompressContinue(zds,
|
||||||
|
zds->outBuff + zds->outStart, dstSize, src, srcSize);
|
||||||
|
FORWARD_IF_ERROR(decodedSize);
|
||||||
|
if (!decodedSize && !isSkipFrame) {
|
||||||
|
zds->streamStage = zdss_read;
|
||||||
|
} else {
|
||||||
|
zds->outEnd = zds->outStart + decodedSize;
|
||||||
|
zds->streamStage = zdss_flush;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t const dstSize = isSkipFrame ? 0 : oend - *op;
|
||||||
|
size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
|
||||||
|
FORWARD_IF_ERROR(decodedSize);
|
||||||
|
*op += decodedSize;
|
||||||
|
zds->streamStage = zdss_read;
|
||||||
|
assert(*op <= oend);
|
||||||
|
assert(zds->outBufferMode == ZSTD_obm_stable);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
|
||||||
{
|
{
|
||||||
const char* const src = (const char*)input->src;
|
const char* const src = (const char*)input->src;
|
||||||
@ -1541,6 +1594,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
"forbidden. out: pos: %u vs size: %u",
|
"forbidden. out: pos: %u vs size: %u",
|
||||||
(U32)output->pos, (U32)output->size);
|
(U32)output->pos, (U32)output->size);
|
||||||
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
|
||||||
|
FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output));
|
||||||
|
|
||||||
while (someMoreWork) {
|
while (someMoreWork) {
|
||||||
switch(zds->streamStage)
|
switch(zds->streamStage)
|
||||||
@ -1551,6 +1605,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
|
||||||
zds->legacyVersion = 0;
|
zds->legacyVersion = 0;
|
||||||
zds->hostageByte = 0;
|
zds->hostageByte = 0;
|
||||||
|
zds->expectedOutBuffer = *output;
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
|
|
||||||
case zdss_loadHeader :
|
case zdss_loadHeader :
|
||||||
@ -1621,6 +1676,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
break;
|
break;
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
/* Check output buffer is large enough for ZSTD_odm_stable. */
|
||||||
|
if (zds->outBufferMode == ZSTD_obm_stable
|
||||||
|
&& zds->fParams.frameType != ZSTD_skippableFrame
|
||||||
|
&& zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
|
||||||
|
&& (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
|
||||||
|
RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
|
||||||
|
}
|
||||||
|
|
||||||
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
/* Consume header (see ZSTDds_decodeFrameHeader) */
|
||||||
DEBUGLOG(4, "Consume header");
|
DEBUGLOG(4, "Consume header");
|
||||||
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)));
|
||||||
@ -1644,7 +1707,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
|
|
||||||
/* Adapt buffer sizes to frame header instructions */
|
/* Adapt buffer sizes to frame header instructions */
|
||||||
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
{ size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
|
||||||
size_t const neededOutBuffSize = ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize);
|
size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered
|
||||||
|
? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
|
||||||
|
: 0;
|
||||||
|
|
||||||
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
|
||||||
|
|
||||||
@ -1687,15 +1752,9 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
|
||||||
int const isSkipFrame = ZSTD_isSkipFrame(zds);
|
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize));
|
||||||
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;
|
ip += neededInSize;
|
||||||
if (!decodedSize && !isSkipFrame) break; /* this was just a header */
|
/* Function modifies the stage so we must break */
|
||||||
zds->outEnd = zds->outStart + decodedSize;
|
|
||||||
zds->streamStage = zdss_flush;
|
|
||||||
break;
|
break;
|
||||||
} }
|
} }
|
||||||
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
|
||||||
@ -1722,17 +1781,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
|
||||||
|
|
||||||
/* decode loaded input */
|
/* decode loaded input */
|
||||||
{ 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 */
|
zds->inPos = 0; /* input is consumed */
|
||||||
if (!decodedSize && !isSkipFrame) { zds->streamStage = zdss_read; break; } /* this was just a header */
|
FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize));
|
||||||
zds->outEnd = zds->outStart + decodedSize;
|
/* Function modifies the stage so we must break */
|
||||||
} }
|
break;
|
||||||
zds->streamStage = zdss_flush;
|
}
|
||||||
/* fall-through */
|
|
||||||
|
|
||||||
case zdss_flush:
|
case zdss_flush:
|
||||||
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
{ size_t const toFlushSize = zds->outEnd - zds->outStart;
|
||||||
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
|
size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize);
|
||||||
@ -1761,6 +1814,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
|
|||||||
/* result */
|
/* result */
|
||||||
input->pos = (size_t)(ip - (const char*)(input->src));
|
input->pos = (size_t)(ip - (const char*)(input->src));
|
||||||
output->pos = (size_t)(op - (char*)(output->dst));
|
output->pos = (size_t)(op - (char*)(output->dst));
|
||||||
|
|
||||||
|
/* Update the expected output buffer for ZSTD_obm_stable. */
|
||||||
|
zds->expectedOutBuffer = *output;
|
||||||
|
|
||||||
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
if ((ip==istart) && (op==ostart)) { /* no forward progress */
|
||||||
zds->noForwardProgress ++;
|
zds->noForwardProgress ++;
|
||||||
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
|
||||||
|
@ -95,6 +95,11 @@ typedef enum {
|
|||||||
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
|
ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
|
||||||
} ZSTD_dictUses_e;
|
} ZSTD_dictUses_e;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ZSTD_obm_buffered = 0, /* Buffer the output */
|
||||||
|
ZSTD_obm_stable = 1 /* ZSTD_outBuffer is stable */
|
||||||
|
} ZSTD_outBufferMode_e;
|
||||||
|
|
||||||
struct ZSTD_DCtx_s
|
struct ZSTD_DCtx_s
|
||||||
{
|
{
|
||||||
const ZSTD_seqSymbol* LLTptr;
|
const ZSTD_seqSymbol* LLTptr;
|
||||||
@ -147,6 +152,8 @@ struct ZSTD_DCtx_s
|
|||||||
U32 legacyVersion;
|
U32 legacyVersion;
|
||||||
U32 hostageByte;
|
U32 hostageByte;
|
||||||
int noForwardProgress;
|
int noForwardProgress;
|
||||||
|
ZSTD_outBufferMode_e outBufferMode;
|
||||||
|
ZSTD_outBuffer expectedOutBuffer;
|
||||||
|
|
||||||
/* workspace */
|
/* workspace */
|
||||||
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
|
BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
|
||||||
|
27
lib/zstd.h
27
lib/zstd.h
@ -523,10 +523,12 @@ typedef enum {
|
|||||||
* within the experimental section of the API.
|
* within the experimental section of the API.
|
||||||
* At the time of this writing, they include :
|
* At the time of this writing, they include :
|
||||||
* ZSTD_d_format
|
* ZSTD_d_format
|
||||||
|
* ZSTD_d_stableOutBuffer
|
||||||
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
|
||||||
* note : never ever use experimentalParam? names directly
|
* note : never ever use experimentalParam? names directly
|
||||||
*/
|
*/
|
||||||
ZSTD_d_experimentalParam1=1000
|
ZSTD_d_experimentalParam1=1000,
|
||||||
|
ZSTD_d_experimentalParam2=1001
|
||||||
|
|
||||||
} ZSTD_dParameter;
|
} ZSTD_dParameter;
|
||||||
|
|
||||||
@ -1645,6 +1647,29 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS
|
|||||||
* allowing selection between ZSTD_format_e input compression formats
|
* allowing selection between ZSTD_format_e input compression formats
|
||||||
*/
|
*/
|
||||||
#define ZSTD_d_format ZSTD_d_experimentalParam1
|
#define ZSTD_d_format ZSTD_d_experimentalParam1
|
||||||
|
/* ZSTD_d_stableOutBuffer
|
||||||
|
* Experimental parameter.
|
||||||
|
* Default is 0 == disabled. Set to 1 to enable.
|
||||||
|
*
|
||||||
|
* Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same
|
||||||
|
* between calls, except for the modifications that zstd makes to pos (the
|
||||||
|
* caller must not modify pos). This is checked by the decompressor, and
|
||||||
|
* decompression will fail if it ever changes. Therefore the ZSTD_outBuffer
|
||||||
|
* MUST be large enough to fit the entire decompressed frame. This will be
|
||||||
|
* checked when the frame content size is known.
|
||||||
|
*
|
||||||
|
* When this flags is enabled zstd won't allocate an output buffer, because
|
||||||
|
* it can write directly to the ZSTD_outBuffer, but it will still allocate
|
||||||
|
* an input buffer large enough to fit any compressed block. This will also
|
||||||
|
* avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer.
|
||||||
|
* If you need to avoid the input buffer allocation use the buffer-less
|
||||||
|
* streaming API.
|
||||||
|
*
|
||||||
|
* NOTE: So long as the ZSTD_outBuffer always points to valid memory, using
|
||||||
|
* this flag is ALWAYS memory safe, and will never access out-of-bounds
|
||||||
|
* memory. However, decompression WILL fail if you violate the preconditions.
|
||||||
|
*/
|
||||||
|
#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2
|
||||||
|
|
||||||
/*! ZSTD_DCtx_setFormat() :
|
/*! ZSTD_DCtx_setFormat() :
|
||||||
* Instruct the decoder context about what kind of data to decode next.
|
* Instruct the decoder context about what kind of data to decode next.
|
||||||
|
@ -641,6 +641,92 @@ static int basicUnitTests(U32 seed, double compressibility)
|
|||||||
}
|
}
|
||||||
DISPLAYLEVEL(3, "OK \n");
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
/* Decompression with ZSTD_d_stableOutBuffer */
|
||||||
|
cSize = ZSTD_compress(compressedBuffer, compressedBufferSize, CNBuffer, CNBufferSize, 1);
|
||||||
|
CHECK_Z(cSize);
|
||||||
|
{ ZSTD_DCtx* dctx = ZSTD_createDCtx();
|
||||||
|
size_t const dctxSize0 = ZSTD_sizeof_DCtx(dctx);
|
||||||
|
size_t dctxSize1;
|
||||||
|
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1));
|
||||||
|
|
||||||
|
outBuff.dst = decodedBuffer;
|
||||||
|
outBuff.pos = 0;
|
||||||
|
outBuff.size = CNBufferSize;
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() single pass : ", testNb++);
|
||||||
|
inBuff.src = compressedBuffer;
|
||||||
|
inBuff.size = cSize;
|
||||||
|
inBuff.pos = 0;
|
||||||
|
{ size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
|
||||||
|
CHECK_Z(r);
|
||||||
|
CHECK(r != 0, "Entire frame must be decompressed");
|
||||||
|
CHECK(outBuff.pos != CNBufferSize, "Wrong size!");
|
||||||
|
CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!");
|
||||||
|
}
|
||||||
|
CHECK(dctxSize0 != ZSTD_sizeof_DCtx(dctx), "No buffers allocated");
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer : ", testNb++);
|
||||||
|
outBuff.pos = 0;
|
||||||
|
inBuff.pos = 0;
|
||||||
|
inBuff.size = 0;
|
||||||
|
while (inBuff.pos < cSize) {
|
||||||
|
inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15));
|
||||||
|
CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff));
|
||||||
|
}
|
||||||
|
CHECK(outBuff.pos != CNBufferSize, "Wrong size!");
|
||||||
|
CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!");
|
||||||
|
dctxSize1 = ZSTD_sizeof_DCtx(dctx);
|
||||||
|
CHECK(!(dctxSize0 < dctxSize1), "Input buffer allocated");
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer too small : ", testNb++);
|
||||||
|
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
|
||||||
|
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1));
|
||||||
|
inBuff.src = compressedBuffer;
|
||||||
|
inBuff.size = cSize;
|
||||||
|
inBuff.pos = 0;
|
||||||
|
outBuff.pos = 0;
|
||||||
|
outBuff.size = CNBufferSize - 1;
|
||||||
|
{ size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
|
||||||
|
CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstSize_tooSmall, "Must error but got %s", ZSTD_getErrorName(r));
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() stable out buffer modified : ", testNb++);
|
||||||
|
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
|
||||||
|
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 1));
|
||||||
|
inBuff.src = compressedBuffer;
|
||||||
|
inBuff.size = cSize - 1;
|
||||||
|
inBuff.pos = 0;
|
||||||
|
outBuff.pos = 0;
|
||||||
|
outBuff.size = CNBufferSize;
|
||||||
|
CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff));
|
||||||
|
++inBuff.size;
|
||||||
|
outBuff.pos = 0;
|
||||||
|
{ size_t const r = ZSTD_decompressStream(dctx, &outBuff, &inBuff);
|
||||||
|
CHECK(ZSTD_getErrorCode(r) != ZSTD_error_dstBuffer_wrong, "Must error but got %s", ZSTD_getErrorName(r));
|
||||||
|
}
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
DISPLAYLEVEL(3, "test%3i : ZSTD_decompressStream() buffered output : ", testNb++);
|
||||||
|
ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only);
|
||||||
|
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_stableOutBuffer, 0));
|
||||||
|
outBuff.pos = 0;
|
||||||
|
inBuff.pos = 0;
|
||||||
|
inBuff.size = 0;
|
||||||
|
while (inBuff.pos < cSize) {
|
||||||
|
inBuff.size += MIN(cSize - inBuff.pos, 1 + (FUZ_rand(&coreSeed) & 15));
|
||||||
|
CHECK_Z(ZSTD_decompressStream(dctx, &outBuff, &inBuff));
|
||||||
|
}
|
||||||
|
CHECK(outBuff.pos != CNBufferSize, "Wrong size!");
|
||||||
|
CHECK(memcmp(CNBuffer, outBuff.dst, CNBufferSize) != 0, "Corruption!");
|
||||||
|
CHECK(!(dctxSize1 < ZSTD_sizeof_DCtx(dctx)), "Output buffer allocated");
|
||||||
|
DISPLAYLEVEL(3, "OK \n");
|
||||||
|
|
||||||
|
ZSTD_freeDCtx(dctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* CDict scenario */
|
/* CDict scenario */
|
||||||
DISPLAYLEVEL(3, "test%3i : digested dictionary : ", testNb++);
|
DISPLAYLEVEL(3, "test%3i : digested dictionary : ", testNb++);
|
||||||
{ ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1 /*byRef*/ );
|
{ ZSTD_CDict* const cdict = ZSTD_createCDict(dictionary.start, dictionary.filled, 1 /*byRef*/ );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user