# include <intrin.h> /* For Visual 2005 */
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
#else
-# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
/* *************************************
* Constants
***************************************/
-ZSTDLIB_API unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
static const U32 g_searchStrength = 8;
+/* *************************************
+* Helper functions
+***************************************/
+unsigned ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
+
+size_t ZSTD_compressBound(size_t srcSize) { return FSE_compressBound(srcSize) + 12; }
+
+
/* *************************************
* Sequence storage
***************************************/
size_t hbSize;
char headerBuffer[ZSTD_frameHeaderSize_max];
-
seqStore_t seqStore; /* sequences storage ptrs */
U32* hashTable;
U32* contentTable;
/* *******************************************************
* Block entropic compression
*********************************************************/
-size_t ZSTD_compressBound(size_t srcSize) /* maximum compressed size */
-{
- return FSE_compressBound(srcSize) + 12;
-}
+/* Block format description
+
+ Block = Literal Section - Sequences Section
+ Prerequisite : size of (compressed) block, maximum size of regenerated data
+
+ 1) Literal Section
+
+ 1.1) Header : 1-5 bytes
+ flags: 2 bits
+ 00 compressed by Huff0
+ 01 unused
+ 10 is Raw (uncompressed)
+ 11 is Rle
+ Note : using 01 => Huff0 with precomputed table ?
+ Note : delta map ? => compressed ?
+
+ 1.1.1) Huff0-compressed literal block : 3-5 bytes
+ srcSize < 1 KB => 3 bytes (2-2-10-10)
+ srcSize < 17KB => 4 bytes (2-2-14-14)
+ else => 5 bytes (2-2-18-18)
+ big endian convention
+
+ 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
+ size : 5 bits: (IS_RAW<<6) + (0<<4) + size
+ 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
+ size&255
+ 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
+ size>>8&255
+ size&255
+
+ 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
+ size : 5 bits: (IS_RLE<<6) + (0<<4) + size
+ 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
+ size&255
+ 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
+ size>>8&255
+ size&255
+
+ 1.1.4) Unused
+ Use Huff0 w/ precalculated DTable ?
+ FSE ? => probably not, not efficient on literals
+
+ 1.2) Literal block content
+
+ 1.2.1) Huff0 block, using sizes from header
+ See Huff0 format
+
+ 1.2.2) Raw content
+
+ 1.2.3) single byte
+
+ 1.2.4) _usingDTable variant ?
+
+
+ 2) Sequences section
+ TO DO
+*/
size_t ZSTD_noCompressBlock (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
static size_t ZSTD_noCompressLiterals (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
BYTE* const ostart = (BYTE* const)dst;
+ const U32 flSize = 1 + (srcSize>31) + (srcSize>4095);
- if (srcSize + 3 > maxDstSize) return ERROR(dstSize_tooSmall);
+ if (srcSize + flSize > maxDstSize) return ERROR(dstSize_tooSmall);
- MEM_writeLE32(dst, ((U32)srcSize << 2) | IS_RAW);
- memcpy(ostart + 3, src, srcSize);
- return srcSize + 3;
+ switch(flSize)
+ {
+ case 1: /* 2 - 1 - 5 */
+ ostart[0] = (BYTE)((IS_RAW<<6) + (0<<5) + srcSize);
+ break;
+ case 2: /* 2 - 2 - 12 */
+ ostart[0] = (BYTE)((IS_RAW<<6) + (2<<4) + (srcSize >> 8));
+ ostart[1] = (BYTE)srcSize;
+ break;
+ default: /*note : should not be necessary : flSize is within {1,2,3} */
+ case 3: /* 2 - 2 - 20 */
+ ostart[0] = (BYTE)((IS_RAW<<6) + (3<<4) + (srcSize >> 16));
+ ostart[1] = (BYTE)(srcSize>>8);
+ ostart[2] = (BYTE)srcSize;
+ break;
+ }
+
+ memcpy(ostart + flSize, src, srcSize);
+ return srcSize + flSize;
}
static size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
BYTE* const ostart = (BYTE* const)dst;
+ U32 flSize = 1 + (srcSize>31) + (srcSize>4095);
+
+ (void)maxDstSize; /* maxDstSize guaranteed to be >=4, hence large enough ? */
+
+ switch(flSize)
+ {
+ case 1: /* 2 - 1 - 5 */
+ ostart[0] = (BYTE)((IS_RLE<<6) + (0<<5) + srcSize);
+ break;
+ case 2: /* 2 - 2 - 12 */
+ ostart[0] = (BYTE)((IS_RLE<<6) + (2<<4) + (srcSize >> 8));
+ ostart[1] = (BYTE)srcSize;
+ break;
+ default: /*note : should not be necessary : flSize is necessary within {1,2,3} */
+ case 3: /* 2 - 2 - 20 */
+ ostart[0] = (BYTE)((IS_RLE<<6) + (3<<4) + (srcSize >> 16));
+ ostart[1] = (BYTE)(srcSize>>8);
+ ostart[2] = (BYTE)srcSize;
+ break;
+ }
- (void)maxDstSize;
- MEM_writeLE32(dst, ((U32)srcSize << 2) | IS_RLE); /* note : maxDstSize > litHeaderSize > 4 */
- ostart[3] = *(const BYTE*)src;
- return 4;
+ ostart[flSize] = *(const BYTE*)src;
+ return flSize+1;
}
+
size_t ZSTD_minGain(size_t srcSize) { return (srcSize >> 6) + 1; }
static size_t ZSTD_compressLiterals (void* dst, size_t maxDstSize,
{
const size_t minGain = ZSTD_minGain(srcSize);
BYTE* const ostart = (BYTE*)dst;
- size_t hsize;
- static const size_t litHeaderSize = 5;
+ size_t lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
+ size_t clitSize;
- if (maxDstSize < litHeaderSize+1) return ERROR(dstSize_tooSmall); /* not enough space for compression */
+ if (maxDstSize < 4) return ERROR(dstSize_tooSmall); /* not enough space for compression */
- hsize = HUF_compress(ostart+litHeaderSize, maxDstSize-litHeaderSize, src, srcSize);
+ clitSize = HUF_compress(ostart+lhSize, maxDstSize-lhSize, src, srcSize);
- if ((hsize==0) || (hsize >= srcSize - minGain)) return ZSTD_noCompressLiterals(dst, maxDstSize, src, srcSize);
- if (hsize==1) return ZSTD_compressRleLiteralsBlock(dst, maxDstSize, src, srcSize);
+ if ((clitSize==0) || (clitSize >= srcSize - minGain)) return ZSTD_noCompressLiterals(dst, maxDstSize, src, srcSize);
+ if (clitSize==1) return ZSTD_compressRleLiteralsBlock(dst, maxDstSize, src, srcSize);
/* Build header */
+ switch(lhSize)
{
- ostart[0] = (BYTE)(srcSize << 2); /* is a block, is compressed */
- ostart[1] = (BYTE)(srcSize >> 6);
- ostart[2] = (BYTE)(srcSize >>14);
- ostart[2] += (BYTE)(hsize << 5);
- ostart[3] = (BYTE)(hsize >> 3);
- ostart[4] = (BYTE)(hsize >>11);
+ case 3: /* 2 - 2 - 10 - 10 */
+ ostart[0] = (BYTE) (srcSize>>6) + (0<< 4);
+ ostart[1] = (BYTE)((srcSize<<2) + (clitSize>>8));
+ ostart[2] = (BYTE)(clitSize);
+ break;
+ case 4: /* 2 - 2 - 14 - 14 */
+ ostart[0] = (BYTE)(srcSize>>10) + (2<<4);
+ ostart[1] = (BYTE)(srcSize>> 2);
+ ostart[2] = (BYTE)((srcSize<<6) + (clitSize>>8));
+ ostart[3] = (BYTE)(clitSize);
+ break;
+ default: /* should not be necessary, lhSize is {3,4,5} */
+ case 5: /* 2 - 2 - 18 - 18 */
+ ostart[0] = (BYTE)(srcSize>>14) + (3<<4);
+ ostart[1] = (BYTE)(srcSize>>6);
+ ostart[2] = (BYTE)((srcSize<<2) + (clitSize>>16));
+ ostart[3] = (BYTE)(clitSize>>8);
+ ostart[4] = (BYTE)(clitSize);
+ break;
}
- return hsize+litHeaderSize;
+ return lhSize+clitSize;
}
FORCE_INLINE
-size_t ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
- void* dst, size_t maxDstSize,
+void ZSTD_compressBlock_fast_generic(ZSTD_CCtx* zc,
const void* src, size_t srcSize,
const U32 mls)
{
memcpy(seqStorePtr->lit, anchor, lastLLSize);
seqStorePtr->lit += lastLLSize;
}
-
- /* Finale compression stage */
- return ZSTD_compressSequences(dst, maxDstSize,
- seqStorePtr, srcSize);
}
-size_t ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
- void* dst, size_t maxDstSize,
- const void* src, size_t srcSize)
+void ZSTD_compressBlock_fast(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize)
{
const U32 mls = ctx->params.searchLength;
switch(mls)
{
default:
case 4 :
- return ZSTD_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 4);
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 4); return;
case 5 :
- return ZSTD_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 5);
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 5); return;
case 6 :
- return ZSTD_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 6);
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 6); return;
case 7 :
- return ZSTD_compressBlock_fast_generic(ctx, dst, maxDstSize, src, srcSize, 7);
+ ZSTD_compressBlock_fast_generic(ctx, src, srcSize, 7); return;
}
}
//FORCE_INLINE
-size_t ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
- void* dst, size_t maxDstSize,
- const void* src, size_t srcSize,
- const U32 mls)
+void ZSTD_compressBlock_fast_extDict_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize,
+ const U32 mls)
{
U32* hashTable = ctx->hashTable;
const U32 hBits = ctx->params.hashLog;
memcpy(seqStorePtr->lit, anchor, lastLLSize);
seqStorePtr->lit += lastLLSize;
}
-
- /* Finale compression stage */
- return ZSTD_compressSequences(dst, maxDstSize,
- seqStorePtr, srcSize);
}
-size_t ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
- void* dst, size_t maxDstSize,
+void ZSTD_compressBlock_fast_extDict(ZSTD_CCtx* ctx,
const void* src, size_t srcSize)
{
const U32 mls = ctx->params.searchLength;
{
default:
case 4 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 4);
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 4);
case 5 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 5);
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 5);
case 6 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 6);
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 6);
case 7 :
- return ZSTD_compressBlock_fast_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 7);
+ return ZSTD_compressBlock_fast_extDict_generic(ctx, src, srcSize, 7);
}
}
* Common parser - lazy strategy
*********************************/
FORCE_INLINE
-size_t ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
- void* dst, size_t maxDstSize, const void* src, size_t srcSize,
+void ZSTD_compressBlock_lazy_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize,
const U32 searchMethod, const U32 depth)
{
seqStore_t* seqStorePtr = &(ctx->seqStore);
memcpy(seqStorePtr->lit, anchor, lastLLSize);
seqStorePtr->lit += lastLLSize;
}
-
- /* Final compression stage */
- return ZSTD_compressSequences(dst, maxDstSize,
- seqStorePtr, srcSize);
}
-size_t ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+static void ZSTD_compressBlock_btlazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, dst, maxDstSize, src, srcSize, 1, 2);
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 1, 2);
}
-size_t ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+static void ZSTD_compressBlock_lazy2(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, dst, maxDstSize, src, srcSize, 0, 2);
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 2);
}
-size_t ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+static void ZSTD_compressBlock_lazy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, dst, maxDstSize, src, srcSize, 0, 1);
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 1);
}
-size_t ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+static void ZSTD_compressBlock_greedy(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_generic(ctx, dst, maxDstSize, src, srcSize, 0, 0);
+ return ZSTD_compressBlock_lazy_generic(ctx, src, srcSize, 0, 0);
}
FORCE_INLINE
-size_t ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
- void* dst, size_t maxDstSize, const void* src, size_t srcSize,
+void ZSTD_compressBlock_lazy_extDict_generic(ZSTD_CCtx* ctx,
+ const void* src, size_t srcSize,
const U32 searchMethod, const U32 depth)
{
seqStore_t* seqStorePtr = &(ctx->seqStore);
memcpy(seqStorePtr->lit, anchor, lastLLSize);
seqStorePtr->lit += lastLLSize;
}
-
- /* Final compression stage */
- return ZSTD_compressSequences(dst, maxDstSize,
- seqStorePtr, srcSize);
}
-size_t ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+void ZSTD_compressBlock_greedy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 0, 0);
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 0);
}
-size_t ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+static void ZSTD_compressBlock_lazy_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 0, 1);
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 1);
}
-size_t ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+static void ZSTD_compressBlock_lazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 0, 2);
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 0, 2);
}
-static size_t ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
+static void ZSTD_compressBlock_btlazy2_extDict(ZSTD_CCtx* ctx, const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_lazy_extDict_generic(ctx, dst, maxDstSize, src, srcSize, 1, 2);
+ return ZSTD_compressBlock_lazy_extDict_generic(ctx, src, srcSize, 1, 2);
}
-typedef size_t (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);
+typedef void (*ZSTD_blockCompressor) (ZSTD_CCtx* ctx, const void* src, size_t srcSize);
-static ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, int extDict)
{
static const ZSTD_blockCompressor blockCompressor[2][5] = {
{ ZSTD_compressBlock_fast, ZSTD_compressBlock_greedy, ZSTD_compressBlock_lazy,ZSTD_compressBlock_lazy2, ZSTD_compressBlock_btlazy2 },
{
ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor(zc->params.strategy, zc->lowLimit < zc->dictLimit);
if (srcSize < MIN_CBLOCK_SIZE+3) return 0; /* don't even attempt compression below a certain srcSize */
- return blockCompressor(zc, dst, maxDstSize, src, srcSize);
+ blockCompressor(zc, src, srcSize);
+ return ZSTD_compressSequences(dst, maxDstSize, &(zc->seqStore), srcSize);
}
/* *************************************************************
* Decompression section
***************************************************************/
+
+/* Frame format description
+ Frame Header - [ Block Header - Block ] - Frame End
+ 1) Frame Header
+ - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_internal.h)
+ - 1 byte - Window Descriptor
+ 2) Block Header
+ - 3 bytes, starting with a 2-bits descriptor
+ Uncompressed, Compressed, Frame End, unused
+ 3) Block
+ See Block Format Description
+ 4) Frame End
+ - 3 bytes, compatible with Block Header
+*/
+
+/* Block format description
+ Literal Section - Sequences Section
+ 1) Literal Section
+ 1.1) Header : up to 5 bytes
+ flags:
+ 00 compressed by Huff0
+ 01 is Raw (uncompressed)
+ 10 is Rle
+ 11 unused
+ Note : using 11 for Huff0 with precomputed table ?
+ Note : delta map ? => compressed ?
+ Note 2 : 19 bits for sizes, seems a bit larger than necessary
+ Note 3 : RLE blocks ?
+
+ 1.2.1) Huff0 block, using sizes from header
+ See Huff0 format
+
+ 1.2.2) Huff0 block, using precomputed DTable
+ _usingDTable variants
+
+ 1.2.3) uncompressed blocks
+ as the name says (both 2 or 3 bytes variants)
+
+ 2) Sequences section
+ TO DO
+*/
+
+
/** ZSTD_decodeFrameHeader_Part1
* decode the 1st part of the Frame Header, which tells Frame Header size.
* srcSize must be == ZSTD_frameHeaderSize_min
return cSize;
}
+
static size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
{
if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
}
-/** ZSTD_decompressLiterals
- @return : nb of bytes read from src, or an error code*/
-static size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,
- const void* src, size_t srcSize)
-{
- const BYTE* ip = (const BYTE*)src;
-
- const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
- const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
-
- if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);
- if (litCSize + 5 > srcSize) return ERROR(corruption_detected);
-
- if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);
-
- *maxDstSizePtr = litSize;
- return litCSize + 5;
-}
-
-
/** ZSTD_decodeLiteralsBlock
@return : nb of bytes read from src (< srcSize ) */
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
/* any compressed block with literals segment must be at least this size */
if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
- switch(*istart & 3)
+ switch(istart[0]>> 6)
{
- /* compressed */
- case 0:
+ case IS_HUF:
{
- size_t litSize = BLOCKSIZE;
- const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);
+ size_t litSize, litCSize;
+ U32 lhSize = ((istart[0]) >> 4) & 3;
+ switch(lhSize)
+ {
+ case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
+ /* 2 - 2 - 10 - 10 */
+ lhSize=3;
+ litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
+ litCSize = ((istart[1] & 3) << 8) + istart[2];
+ break;
+ case 2:
+ /* 2 - 2 - 14 - 14 */
+ lhSize=4;
+ litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);
+ litCSize = ((istart[2] & 63) << 8) + istart[3];
+ break;
+ case 3:
+ /* 2 - 2 - 18 - 18 */
+ lhSize=5;
+ litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);
+ litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];
+ break;
+ }
+
+ if (HUF_isError( HUF_decompress(dctx->litBuffer, litSize, istart+lhSize, litCSize) ))
+ return ERROR(corruption_detected);
+
dctx->litPtr = dctx->litBuffer;
dctx->litBufSize = BLOCKSIZE+8;
dctx->litSize = litSize;
- return readSize; /* works if it's an error too */
+ return litCSize + lhSize;
}
case IS_RAW:
{
- const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
- if (litSize > srcSize-11) /* risk of reading too far with wildcopy */
+ size_t litSize;
+ U32 lhSize = ((istart[0]) >> 4) & 3;
+ switch(lhSize)
+ {
+ case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
+ lhSize=1;
+ litSize = istart[0] & 31;
+ break;
+ case 2:
+ litSize = ((istart[0] & 15) << 8) + istart[1];
+ break;
+ case 3:
+ litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
+ break;
+ }
+
+ if (litSize > srcSize-11) /* risk of reading beyond src buffer with wildcopy */
{
- if (litSize > srcSize-3) return ERROR(corruption_detected);
- memcpy(dctx->litBuffer, istart, litSize);
+ if (litSize > srcSize-litSize) return ERROR(corruption_detected);
+ memcpy(dctx->litBuffer, istart+lhSize, litSize);
dctx->litPtr = dctx->litBuffer;
dctx->litBufSize = BLOCKSIZE+8;
dctx->litSize = litSize;
- return litSize+3;
+ return litSize+lhSize;
}
/* direct reference into compressed stream */
- dctx->litPtr = istart+3;
- dctx->litBufSize = srcSize-3;
+ dctx->litPtr = istart+lhSize;
+ dctx->litBufSize = srcSize-lhSize;
dctx->litSize = litSize;
- return litSize+3; }
+ return lhSize+litSize;
+ }
case IS_RLE:
{
- const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2; /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */
+ size_t litSize;
+ U32 lhSize = ((istart[0]) >> 4) & 3;
+ switch(lhSize)
+ {
+ case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
+ lhSize = 1;
+ litSize = istart[0] & 31;
+ break;
+ case 2:
+ litSize = ((istart[0] & 15) << 8) + istart[1];
+ break;
+ case 3:
+ litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
+ break;
+ }
if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
- memset(dctx->litBuffer, istart[3], litSize);
+ memset(dctx->litBuffer, istart[lhSize], litSize);
dctx->litPtr = dctx->litBuffer;
dctx->litBufSize = BLOCKSIZE+8;
dctx->litSize = litSize;
- return 4;
+ return lhSize+1;
}
- default:
- return ERROR(corruption_detected); /* forbidden nominal case */
+ default: /* IS_PCH */
+ return ERROR(corruption_detected); /* not yet nominal case */
}
}