Support legacy ZSTD_decompress_usingDict() (starting v0.5+)

This commit is contained in:
Yann Collet 2016-05-06 16:43:23 +02:00
parent 8283a2f0aa
commit 18dedece91
3 changed files with 60 additions and 45 deletions

View File

@ -842,14 +842,14 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
} }
/*! ZSTD_decompress_continueDCtx() : /*! ZSTD_decompressFrame() :
* `dctx` must have been properly initialized */ * `dctx` must be properly initialized */
static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity, void* dst, size_t dstCapacity,
const void* src, size_t srcSize) const void* src, size_t srcSize)
{ {
const BYTE* ip = (const BYTE*)src; const BYTE* ip = (const BYTE*)src;
const BYTE* iend = ip + srcSize; const BYTE* const iend = ip + srcSize;
BYTE* const ostart = (BYTE* const)dst; BYTE* const ostart = (BYTE* const)dst;
BYTE* op = ostart; BYTE* op = ostart;
BYTE* const oend = ostart + dstCapacity; BYTE* const oend = ostart + dstCapacity;
@ -858,12 +858,6 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
/* check */ /* check */
if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
{ const U32 magicNumber = MEM_readLE32(src);
if (ZSTD_isLegacy(magicNumber))
return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, magicNumber);
}
#endif
/* Frame Header */ /* Frame Header */
{ size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min); { size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
@ -928,6 +922,12 @@ size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
const void* src, size_t srcSize, const void* src, size_t srcSize,
const void* dict, size_t dictSize) const void* dict, size_t dictSize)
{ {
#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
{ const U32 magicNumber = MEM_readLE32(src);
if (ZSTD_isLegacy(magicNumber))
return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, dict, dictSize, magicNumber);
}
#endif
ZSTD_decompressBegin_usingDict(dctx, dict, dictSize); ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
ZSTD_checkContinuity(dctx, dst); ZSTD_checkContinuity(dctx, dst);
return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize); return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
@ -949,7 +949,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize); regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
ZSTD_freeDCtx(dctx); ZSTD_freeDCtx(dctx);
return regenSize; return regenSize;
#else #else /* stack mode */
ZSTD_DCtx dctx; ZSTD_DCtx dctx;
return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize); return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
#endif #endif
@ -1053,37 +1053,40 @@ static void ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSi
static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
{ {
size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize; size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize;
short offcodeNCount[MaxOff+1];
U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
short matchlengthNCount[MaxML+1];
unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
short litlengthNCount[MaxLL+1];
unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize); hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize);
if (HUF_isError(hSize)) return ERROR(dictionary_corrupted); if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
dict = (const char*)dict + hSize; dict = (const char*)dict + hSize;
dictSize -= hSize; dictSize -= hSize;
offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize); { short offcodeNCount[MaxOff+1];
if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted); U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog); offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
dict = (const char*)dict + offcodeHeaderSize; { size_t const errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
dictSize -= offcodeHeaderSize; if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
dict = (const char*)dict + offcodeHeaderSize;
dictSize -= offcodeHeaderSize;
}
matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize); { short matchlengthNCount[MaxML+1];
if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted); unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog); matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
dict = (const char*)dict + matchlengthHeaderSize; { size_t const errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
dictSize -= matchlengthHeaderSize; if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
dict = (const char*)dict + matchlengthHeaderSize;
dictSize -= matchlengthHeaderSize;
}
litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize); { short litlengthNCount[MaxLL+1];
if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted); unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog); litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
{ size_t const errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted); }
}
dctx->flagRepeatTable = 1; dctx->flagRepeatTable = 1;
return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize; return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;

View File

@ -1,7 +1,7 @@
/* /*
zstd_legacy - decoder for legacy format zstd_legacy - decoder for legacy format
Header File Header File
Copyright (C) 2015, Yann Collet. Copyright (C) 2015-2016, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
@ -48,16 +48,20 @@ extern "C" {
#include "zstd_v04.h" #include "zstd_v04.h"
#include "zstd_v05.h" #include "zstd_v05.h"
/** ZSTD_isLegacy() :
@return : > 0 if supported by legacy decoder. 0 otherwise.
return value is the version.
*/
MEM_STATIC unsigned ZSTD_isLegacy (U32 magicNumberLE) MEM_STATIC unsigned ZSTD_isLegacy (U32 magicNumberLE)
{ {
switch(magicNumberLE) switch(magicNumberLE)
{ {
case ZSTDv01_magicNumberLE : case ZSTDv01_magicNumberLE:return 1;
case ZSTDv02_magicNumber : case ZSTDv02_magicNumber : return 2;
case ZSTDv03_magicNumber : case ZSTDv03_magicNumber : return 3;
case ZSTDv04_magicNumber : case ZSTDv04_magicNumber : return 4;
case ZSTDv05_MAGICNUMBER : case ZSTDv05_MAGICNUMBER : return 5;
return 1;
default : return 0; default : return 0;
} }
} }
@ -66,6 +70,7 @@ MEM_STATIC unsigned ZSTD_isLegacy (U32 magicNumberLE)
MEM_STATIC size_t ZSTD_decompressLegacy( MEM_STATIC size_t ZSTD_decompressLegacy(
void* dst, size_t dstCapacity, void* dst, size_t dstCapacity,
const void* src, size_t compressedSize, const void* src, size_t compressedSize,
const void* dict,size_t dictSize,
U32 magicNumberLE) U32 magicNumberLE)
{ {
switch(magicNumberLE) switch(magicNumberLE)
@ -79,7 +84,14 @@ MEM_STATIC size_t ZSTD_decompressLegacy(
case ZSTDv04_magicNumber : case ZSTDv04_magicNumber :
return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize); return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize);
case ZSTDv05_MAGICNUMBER : case ZSTDv05_MAGICNUMBER :
return ZSTDv05_decompress(dst, dstCapacity, src, compressedSize); {
size_t result;
ZSTDv05_DCtx* zd = ZSTDv05_createDCtx();
if (zd==NULL) return ERROR(memory_allocation);
result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);
ZSTDv05_freeDCtx(zd);
return result;
}
default : default :
return ERROR(prefix_unknown); return ERROR(prefix_unknown);
} }

View File

@ -69,7 +69,7 @@ const char* ZSTDv05_getErrorName(size_t code); /*!< provides readable string
/** Decompression context */ /** Decompression context */
typedef struct ZSTDv05_DCtx_s ZSTDv05_DCtx; typedef struct ZSTDv05_DCtx_s ZSTDv05_DCtx;
ZSTDv05_DCtx* ZSTDv05_createDCtx(void); ZSTDv05_DCtx* ZSTDv05_createDCtx(void);
size_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx); /*!< @return : errorCode */ size_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx); /*!< @return : errorCode */
/** ZSTDv05_decompressDCtx() : /** ZSTDv05_decompressDCtx() :
* Same as ZSTDv05_decompress(), but requires an already allocated ZSTDv05_DCtx (see ZSTDv05_createDCtx()) */ * Same as ZSTDv05_decompress(), but requires an already allocated ZSTDv05_DCtx (see ZSTDv05_createDCtx()) */
@ -84,9 +84,9 @@ size_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* ctx, void* dst, size_t dstCapacity,
* Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted. * Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted.
* Note : dict can be NULL, in which case, it's equivalent to ZSTDv05_decompressDCtx() */ * Note : dict can be NULL, in which case, it's equivalent to ZSTDv05_decompressDCtx() */
size_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx, size_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx,
void* dst, size_t dstCapacity, void* dst, size_t dstCapacity,
const void* src, size_t srcSize, const void* src, size_t srcSize,
const void* dict,size_t dictSize); const void* dict,size_t dictSize);