1
0
mirror of https://github.com/facebook/zstd.git synced 2025-03-06 16:56:49 +02:00

New streaming API behavior, to solve issue 19 (https://github.com/Cyan4973/zstd/issues/19)

This commit is contained in:
Yann Collet 2015-02-16 18:06:26 +01:00
parent f66d2babf8
commit c5d46b5c90
4 changed files with 61 additions and 54 deletions

View File

@ -141,7 +141,7 @@ static const U32 ZSTD_magicNumber = 0xFD2FB51C; /* Initial (limited) frame for
#define KB *(1 <<10) #define KB *(1 <<10)
#define MB *(1 <<20) #define MB *(1 <<20)
#define GB *(1U<<20) #define GB *(1U<<30)
#define BLOCKSIZE (128 KB) /* define, for static allocation */ #define BLOCKSIZE (128 KB) /* define, for static allocation */
static const U32 g_maxDistance = 512 KB; static const U32 g_maxDistance = 512 KB;
@ -1708,24 +1708,24 @@ size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t src
} }
/****************************** /*******************************
* Streaming Decompression API * Streaming Decompression API
******************************/ *******************************/
typedef struct typedef struct
{ {
U32 ctx[FSE_DTABLE_SIZE_U32(LLFSELog) + FSE_DTABLE_SIZE_U32(OffFSELog) + FSE_DTABLE_SIZE_U32(MLFSELog)]; U32 ctx[FSE_DTABLE_SIZE_U32(LLFSELog) + FSE_DTABLE_SIZE_U32(OffFSELog) + FSE_DTABLE_SIZE_U32(MLFSELog)];
size_t expected; size_t expected;
blockType_t bType; blockType_t bType;
U32 started; U32 phase;
} dctx_t; } dctx_t;
ZSTD_dctx_t ZSTD_createDCtx(void) ZSTD_dctx_t ZSTD_createDCtx(void)
{ {
dctx_t* dctx = (dctx_t*)malloc(sizeof(dctx_t)); dctx_t* dctx = (dctx_t*)malloc(sizeof(dctx_t));
dctx->expected = 4 + ZSTD_blockHeaderSize; // Frame Header + Block Header dctx->expected = ZSTD_frameHeaderSize;
dctx->started = 0; dctx->phase = 0;
return (ZSTD_dctx_t)dctx; return (ZSTD_dctx_t)dctx;
} }
@ -1736,7 +1736,7 @@ size_t ZSTD_freeDCtx(ZSTD_dctx_t dctx)
} }
size_t ZSTD_getNextcBlockSize(ZSTD_dctx_t dctx) size_t ZSTD_nextSrcSizeToDecompress(ZSTD_dctx_t dctx)
{ {
return ((dctx_t*)dctx)->expected; return ((dctx_t*)dctx)->expected;
} }
@ -1744,63 +1744,67 @@ size_t ZSTD_getNextcBlockSize(ZSTD_dctx_t dctx)
size_t ZSTD_decompressContinue(ZSTD_dctx_t dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize) size_t ZSTD_decompressContinue(ZSTD_dctx_t dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{ {
dctx_t* ctx = (dctx_t*)dctx; dctx_t* ctx = (dctx_t*)dctx;
size_t cSize = srcSize - ZSTD_blockHeaderSize;
size_t rSize;
// Sanity check /* Sanity check */
if (srcSize != ctx->expected) return (size_t)-ZSTD_ERROR_wrongSrcSize; if (srcSize != ctx->expected) return (size_t)-ZSTD_ERROR_wrongSrcSize;
// Decompress /* Decompress : frame header */
if (!ctx->started) if (ctx->phase == 0)
{ {
// Just check correct magic header /* Check frame magic header */
U32 magicNumber = ZSTD_readBE32(src); U32 magicNumber = ZSTD_readBE32(src);
if (magicNumber != ZSTD_magicNumber) return (size_t)-ZSTD_ERROR_wrongMagicNumber; if (magicNumber != ZSTD_magicNumber) return (size_t)-ZSTD_ERROR_wrongMagicNumber;
rSize = 0; ctx->phase = 1;
ctx->expected = ZSTD_blockHeaderSize;
return 0;
} }
else
/* Decompress : block header */
if (ctx->phase == 1)
{ {
blockProperties_t bp;
size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
if (ZSTD_isError(blockSize)) return blockSize;
if (bp.blockType == bt_end)
{
ctx->expected = 0;
ctx->phase = 0;
}
else
{
ctx->expected = blockSize;
ctx->bType = bp.blockType;
ctx->phase = 2;
}
return 0;
}
/* Decompress : block content */
{
size_t rSize;
switch(ctx->bType) switch(ctx->bType)
{ {
case bt_compressed: case bt_compressed:
rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, cSize); rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);
break; break;
case bt_raw : case bt_raw :
rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, cSize); rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);
break; break;
case bt_rle : case bt_rle :
return (size_t)-ZSTD_ERROR_GENERIC; /* not yet handled */ return (size_t)-ZSTD_ERROR_GENERIC; /* not yet handled */
break; break;
case bt_end : case bt_end : /* should never happen (filtered at phase 1) */
rSize = 0; rSize = 0;
break; break;
default: default:
return (size_t)-ZSTD_ERROR_GENERIC; return (size_t)-ZSTD_ERROR_GENERIC;
} }
ctx->phase = 1;
ctx->expected = ZSTD_blockHeaderSize;
return rSize;
} }
// Prepare next block
{
const BYTE* header = (const BYTE*)src;
blockProperties_t bp;
size_t blockSize;
header += cSize;
blockSize = ZSTD_getcBlockSize(header, ZSTD_blockHeaderSize, &bp);
if (ZSTD_isError(blockSize)) return blockSize;
if (bp.blockType == bt_end)
{
ctx->expected = 0;
ctx->started = 0;
}
else
{
ctx->expected = blockSize + ZSTD_blockHeaderSize;
ctx->bType = bp.blockType;
ctx->started = 1;
}
}
return rSize;
} }

View File

@ -47,7 +47,7 @@ extern "C" {
**************************************/ **************************************/
#define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */ #define ZSTD_VERSION_MAJOR 0 /* for breaking interface changes */
#define ZSTD_VERSION_MINOR 0 /* for new (non-breaking) interface capabilities */ #define ZSTD_VERSION_MINOR 0 /* for new (non-breaking) interface capabilities */
#define ZSTD_VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */ #define ZSTD_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
unsigned ZSTD_versionNumber (void); unsigned ZSTD_versionNumber (void);

View File

@ -57,7 +57,7 @@ typedef void* ZSTD_dctx_t;
ZSTD_dctx_t ZSTD_createDCtx(void); ZSTD_dctx_t ZSTD_createDCtx(void);
size_t ZSTD_freeDCtx(ZSTD_dctx_t dctx); size_t ZSTD_freeDCtx(ZSTD_dctx_t dctx);
size_t ZSTD_getNextcBlockSize(ZSTD_dctx_t dctx); size_t ZSTD_nextSrcSizeToDecompress(ZSTD_dctx_t dctx);
size_t ZSTD_decompressContinue(ZSTD_dctx_t dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize); size_t ZSTD_decompressContinue(ZSTD_dctx_t dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);
@ -77,4 +77,4 @@ typedef enum { ZSTD_LIST_ERRORS(ZSTD_GENERATE_ENUM) } ZSTD_errorCodes; /* expo
#if defined (__cplusplus) #if defined (__cplusplus)
} }
#endif #endif

View File

@ -327,10 +327,10 @@ unsigned long long FIO_decompressFilename(const char* output_filename, const cha
/* Init */ /* Init */
FIO_getFileHandles(&finput, &foutput, input_filename, output_filename); FIO_getFileHandles(&finput, &foutput, input_filename, output_filename);
dctx = ZSTD_createDCtx(); dctx = ZSTD_createDCtx();
toRead = ZSTD_getNextcBlockSize(dctx);
if (toRead > MAXHEADERSIZE) EXM_THROW(30, "Not enough memory to read header");
/* check header */ /* check header */
toRead = ZSTD_nextSrcSizeToDecompress(dctx);
if (toRead > MAXHEADERSIZE) EXM_THROW(30, "Not enough memory to read header");
sizeCheck = fread(header, (size_t)1, toRead, finput); sizeCheck = fread(header, (size_t)1, toRead, finput);
if (sizeCheck != toRead) EXM_THROW(31, "Read error : cannot read header"); if (sizeCheck != toRead) EXM_THROW(31, "Read error : cannot read header");
sizeCheck = ZSTD_decompressContinue(dctx, NULL, 0, header, toRead); // Decode frame header sizeCheck = ZSTD_decompressContinue(dctx, NULL, 0, header, toRead); // Decode frame header
@ -348,7 +348,7 @@ unsigned long long FIO_decompressFilename(const char* output_filename, const cha
if (!inBuff || !outBuff) EXM_THROW(33, "Allocation error : not enough memory"); if (!inBuff || !outBuff) EXM_THROW(33, "Allocation error : not enough memory");
/* Main decompression Loop */ /* Main decompression Loop */
toRead = ZSTD_getNextcBlockSize(dctx); toRead = ZSTD_nextSrcSizeToDecompress(dctx);
while (toRead) while (toRead)
{ {
size_t readSize, decodedSize; size_t readSize, decodedSize;
@ -361,16 +361,19 @@ unsigned long long FIO_decompressFilename(const char* output_filename, const cha
/* Decode block */ /* Decode block */
decodedSize = ZSTD_decompressContinue(dctx, op, oend-op, inBuff, readSize); decodedSize = ZSTD_decompressContinue(dctx, op, oend-op, inBuff, readSize);
/* Write block */ if (decodedSize) /* not a header */
sizeCheck = fwrite(op, 1, decodedSize, foutput); {
if (sizeCheck != decodedSize) EXM_THROW(35, "Write error : unable to write data block to destination file"); /* Write block */
filesize += decodedSize; sizeCheck = fwrite(op, 1, decodedSize, foutput);
if (sizeCheck != decodedSize) EXM_THROW(35, "Write error : unable to write data block to destination file");
filesize += decodedSize;
op += decodedSize;
if (op==oend) op = outBuff;
DISPLAYUPDATE(2, "\rDecoded : %u MB... ", (U32)(filesize>>20) );
}
/* prepare for next Block */ /* prepare for next Block */
op += decodedSize; toRead = ZSTD_nextSrcSizeToDecompress(dctx);
if (op==oend) op = outBuff;
toRead = ZSTD_getNextcBlockSize(dctx);
DISPLAYUPDATE(2, "\rDecoded : %u MB... ", (U32)(filesize>>20) );
} }
DISPLAYLEVEL(2, "\r%79s\r", ""); DISPLAYLEVEL(2, "\r%79s\r", "");