blob: 35404417e3f12d3d036f43e2d2b3f3ea3082fa75 [file] [log] [blame]
Yann Collet5be2dd22015-11-11 13:43:58 +01001/*
2 zstd - standard compression library
Yann Colletae7aa062016-02-03 02:46:46 +01003 Copyright (C) 2014-2016, Yann Collet.
Yann Collet5be2dd22015-11-11 13:43:58 +01004
5 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are
9 met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 copyright notice, this list of conditions and the following disclaimer
14 in the documentation and/or other materials provided with the
15 distribution.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 You can contact the author at :
Yann Collet01e5b952016-03-19 14:14:31 +010029 - zstd homepage : http://www.zstd.net
Yann Collet5be2dd22015-11-11 13:43:58 +010030*/
31
32/* ***************************************************************
33* Tuning parameters
34*****************************************************************/
35/*!
Yann Collet5be2dd22015-11-11 13:43:58 +010036 * HEAPMODE :
Yann Collet3a3b72f2016-01-11 12:56:11 +010037 * Select how default decompression function ZSTD_decompress() will allocate memory,
38 * in memory stack (0), or in memory heap (1, requires malloc())
Yann Collet5be2dd22015-11-11 13:43:58 +010039 */
40#ifndef ZSTD_HEAPMODE
41# define ZSTD_HEAPMODE 1
Yann Collet3a3b72f2016-01-11 12:56:11 +010042#endif
Yann Collet5be2dd22015-11-11 13:43:58 +010043
44/*!
45* LEGACY_SUPPORT :
Yann Colletae7aa062016-02-03 02:46:46 +010046* if set to 1, ZSTD_decompress() can decode older formats (v0.1+)
Yann Collet5be2dd22015-11-11 13:43:58 +010047*/
48#ifndef ZSTD_LEGACY_SUPPORT
Yann Colletfba6aed2016-01-18 12:03:27 +010049# define ZSTD_LEGACY_SUPPORT 0
Yann Collet5be2dd22015-11-11 13:43:58 +010050#endif
51
52
Yann Colletfb810d62016-01-28 00:18:06 +010053/*-*******************************************************
Yann Collet953ce722016-02-04 15:28:14 +010054* Dependencies
Yann Collet5be2dd22015-11-11 13:43:58 +010055*********************************************************/
56#include <stdlib.h> /* calloc */
57#include <string.h> /* memcpy, memmove */
Yann Collet953ce722016-02-04 15:28:14 +010058#include <stdio.h> /* debug only : printf */
Yann Collet5be2dd22015-11-11 13:43:58 +010059#include "mem.h" /* low level memory routines */
Yann Collet5be2dd22015-11-11 13:43:58 +010060#include "zstd_internal.h"
61#include "fse_static.h"
Yann Colletafe07092016-01-25 04:10:46 +010062#include "huff0_static.h"
Yann Collet5be2dd22015-11-11 13:43:58 +010063
64#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
65# include "zstd_legacy.h"
66#endif
67
Yann Colletfb810d62016-01-28 00:18:06 +010068
69/*-*******************************************************
Yann Collet5be2dd22015-11-11 13:43:58 +010070* Compiler specifics
71*********************************************************/
Yann Collet5be2dd22015-11-11 13:43:58 +010072#ifdef _MSC_VER /* Visual Studio */
73# define FORCE_INLINE static __forceinline
74# include <intrin.h> /* For Visual 2005 */
75# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
76# pragma warning(disable : 4324) /* disable: C4324: padded structure */
77#else
78# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
79# ifdef __GNUC__
80# define FORCE_INLINE static inline __attribute__((always_inline))
81# else
82# define FORCE_INLINE static inline
83# endif
84#endif
85
86
Yann Collet03ea59b2016-03-12 01:25:40 +010087/*_*******************************************************
Yann Collet5be2dd22015-11-11 13:43:58 +010088* Memory operations
89**********************************************************/
90static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
91
92
Yann Collet03ea59b2016-03-12 01:25:40 +010093/*-*************************************
Yann Collet5be2dd22015-11-11 13:43:58 +010094* Error Management
95***************************************/
Yann Collet14983e72015-11-11 21:38:21 +010096unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; }
97
Yann Collet953ce722016-02-04 15:28:14 +010098/*! ZSTD_isError() :
Yann Collet5be2dd22015-11-11 13:43:58 +010099* tells if a return value is an error code */
100unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
101
Yann Collet953ce722016-02-04 15:28:14 +0100102/*! ZSTD_getError() :
Yann Collet72bff502016-02-03 12:06:24 +0100103* convert a `size_t` function result into a proper ZSTD_errorCode enum */
Yann Collet982ffc72016-02-05 02:33:10 +0100104ZSTD_ErrorCode ZSTD_getError(size_t code) { return ERR_getError(code); }
Yann Collet72bff502016-02-03 12:06:24 +0100105
Yann Collet953ce722016-02-04 15:28:14 +0100106/*! ZSTD_getErrorName() :
Yann Collet5be2dd22015-11-11 13:43:58 +0100107* provides error code string (useful for debugging) */
108const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }
109
110
Yann Collet03ea59b2016-03-12 01:25:40 +0100111/*-*************************************************************
Yann Collet5b78d2f2015-11-12 15:36:05 +0100112* Context management
Yann Collet5be2dd22015-11-11 13:43:58 +0100113***************************************************************/
Yann Collete4fdad52015-11-25 21:09:17 +0100114typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
Yann Collet88fcd292015-11-25 14:42:45 +0100115 ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTD_dStage;
116
Yann Collet5be2dd22015-11-11 13:43:58 +0100117struct ZSTD_DCtx_s
118{
Yann Colletfb810d62016-01-28 00:18:06 +0100119 FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
120 FSE_DTable OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
121 FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
122 unsigned hufTableX4[HUF_DTABLE_SIZE(HufLog)];
Yann Collet417890c2015-12-04 17:16:37 +0100123 const void* previousDstEnd;
124 const void* base;
125 const void* vBase;
126 const void* dictEnd;
Yann Collet5be2dd22015-11-11 13:43:58 +0100127 size_t expected;
Yann Collet88fcd292015-11-25 14:42:45 +0100128 size_t headerSize;
Yann Collet0e491c02016-03-11 21:58:04 +0100129 ZSTD_frameParams fParams;
Yann Colletfb810d62016-01-28 00:18:06 +0100130 blockType_t bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
Yann Collet88fcd292015-11-25 14:42:45 +0100131 ZSTD_dStage stage;
Yann Colletfb810d62016-01-28 00:18:06 +0100132 U32 flagStaticTables;
Yann Collet5be2dd22015-11-11 13:43:58 +0100133 const BYTE* litPtr;
134 size_t litBufSize;
135 size_t litSize;
Yann Collet569b81a2016-03-16 15:26:51 +0100136 BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
Yann Collet0e491c02016-03-11 21:58:04 +0100137 BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
Yann Collet417890c2015-12-04 17:16:37 +0100138}; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */
Yann Collet5be2dd22015-11-11 13:43:58 +0100139
Yann Colletfb810d62016-01-28 00:18:06 +0100140size_t sizeofDCtx (void) { return sizeof(ZSTD_DCtx); }
141
Yann Collet7b51a292016-01-26 15:58:49 +0100142size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
Yann Collet5b78d2f2015-11-12 15:36:05 +0100143{
Yann Collet88fcd292015-11-25 14:42:45 +0100144 dctx->expected = ZSTD_frameHeaderSize_min;
145 dctx->stage = ZSTDds_getFrameHeaderSize;
Yann Collet5b78d2f2015-11-12 15:36:05 +0100146 dctx->previousDstEnd = NULL;
147 dctx->base = NULL;
148 dctx->vBase = NULL;
149 dctx->dictEnd = NULL;
Yann Colletb923f652016-01-26 03:14:20 +0100150 dctx->hufTableX4[0] = HufLog;
Yann Colletfb810d62016-01-28 00:18:06 +0100151 dctx->flagStaticTables = 0;
Yann Collet0e491c02016-03-11 21:58:04 +0100152 dctx->fParams.mml = MINMATCH; /* overwritten by frame but forces ZSTD_btopt to MINMATCH in block mode */
inikepa4dde252016-03-01 14:14:35 +0100153 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin searchLength=%d\n", dctx->base, dctx->params.searchLength);
Yann Collet5b78d2f2015-11-12 15:36:05 +0100154 return 0;
155}
156
157ZSTD_DCtx* ZSTD_createDCtx(void)
158{
159 ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));
160 if (dctx==NULL) return NULL;
Yann Collet7b51a292016-01-26 15:58:49 +0100161 ZSTD_decompressBegin(dctx);
Yann Collet5b78d2f2015-11-12 15:36:05 +0100162 return dctx;
163}
164
165size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
166{
167 free(dctx);
Yann Collet982ffc72016-02-05 02:33:10 +0100168 return 0; /* reserved as a potential error code in the future */
Yann Collet5b78d2f2015-11-12 15:36:05 +0100169}
170
Yann Collet7b51a292016-01-26 15:58:49 +0100171void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
172{
173 memcpy(dstDCtx, srcDCtx,
Yann Collet569b81a2016-03-16 15:26:51 +0100174 sizeof(ZSTD_DCtx) - (ZSTD_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH + ZSTD_frameHeaderSize_max)); /* no need to copy workspace */
Yann Collet7b51a292016-01-26 15:58:49 +0100175}
176
Yann Collet5b78d2f2015-11-12 15:36:05 +0100177
Yann Collet03ea59b2016-03-12 01:25:40 +0100178/*-*************************************************************
Yann Collet5b78d2f2015-11-12 15:36:05 +0100179* Decompression section
180***************************************************************/
Yann Collet59d1f792016-01-23 19:28:41 +0100181
182/* Frame format description
183 Frame Header - [ Block Header - Block ] - Frame End
184 1) Frame Header
Yann Collet03ea59b2016-03-12 01:25:40 +0100185 - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h)
186 - 1 byte - Frame Descriptor
Yann Collet59d1f792016-01-23 19:28:41 +0100187 2) Block Header
188 - 3 bytes, starting with a 2-bits descriptor
189 Uncompressed, Compressed, Frame End, unused
190 3) Block
191 See Block Format Description
192 4) Frame End
193 - 3 bytes, compatible with Block Header
194*/
195
Yann Collet03ea59b2016-03-12 01:25:40 +0100196
197/* Frame descriptor
198
199 1 byte, using :
200 bit 0-3 : windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN (see zstd_internal.h)
201 bit 4 : minmatch 4(0) or 3(1)
202 bit 5 : reserved (must be zero)
203 bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes
Yann Colletfb797352016-03-13 11:08:40 +0100204
205 Optional : content size (0, 1, 2 or 8 bytes)
206 0 : unknown
207 1 : 0-255 bytes
208 2 : 256 - 65535+256
209 8 : up to 16 exa
Yann Collet03ea59b2016-03-12 01:25:40 +0100210*/
211
212
213/* Compressed Block, format description
Yann Colletfb810d62016-01-28 00:18:06 +0100214
215 Block = Literal Section - Sequences Section
216 Prerequisite : size of (compressed) block, maximum size of regenerated data
217
Yann Collet59d1f792016-01-23 19:28:41 +0100218 1) Literal Section
Yann Colletfb810d62016-01-28 00:18:06 +0100219
220 1.1) Header : 1-5 bytes
221 flags: 2 bits
Yann Collet59d1f792016-01-23 19:28:41 +0100222 00 compressed by Huff0
Yann Colletfb810d62016-01-28 00:18:06 +0100223 01 unused
224 10 is Raw (uncompressed)
225 11 is Rle
226 Note : using 01 => Huff0 with precomputed table ?
Yann Collet59d1f792016-01-23 19:28:41 +0100227 Note : delta map ? => compressed ?
Yann Colletfb810d62016-01-28 00:18:06 +0100228
229 1.1.1) Huff0-compressed literal block : 3-5 bytes
230 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
231 srcSize < 1 KB => 3 bytes (2-2-10-10)
232 srcSize < 16KB => 4 bytes (2-2-14-14)
233 else => 5 bytes (2-2-18-18)
234 big endian convention
235
236 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
237 size : 5 bits: (IS_RAW<<6) + (0<<4) + size
238 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
239 size&255
240 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
241 size>>8&255
242 size&255
243
244 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
245 size : 5 bits: (IS_RLE<<6) + (0<<4) + size
246 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
247 size&255
248 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
249 size>>8&255
250 size&255
251
252 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
253 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
254 srcSize < 1 KB => 3 bytes (2-2-10-10)
255 srcSize < 16KB => 4 bytes (2-2-14-14)
256 else => 5 bytes (2-2-18-18)
257 big endian convention
258
259 1- CTable available (stored into workspace ?)
260 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
261
262
263 1.2) Literal block content
Yann Collet59d1f792016-01-23 19:28:41 +0100264
265 1.2.1) Huff0 block, using sizes from header
266 See Huff0 format
267
Yann Colletfb810d62016-01-28 00:18:06 +0100268 1.2.2) Huff0 block, using prepared table
Yann Collet59d1f792016-01-23 19:28:41 +0100269
Yann Colletfb810d62016-01-28 00:18:06 +0100270 1.2.3) Raw content
271
272 1.2.4) single byte
273
Yann Collet59d1f792016-01-23 19:28:41 +0100274
275 2) Sequences section
276 TO DO
277*/
278
Yann Collet03ea59b2016-03-12 01:25:40 +0100279static const size_t ZSTD_fcs_fieldSize[4] = { 0, 1, 2, 8 };
Yann Collet59d1f792016-01-23 19:28:41 +0100280
Yann Collet03ea59b2016-03-12 01:25:40 +0100281/** ZSTD_frameHeaderSize() :
282* srcSize must be >= ZSTD_frameHeaderSize_min.
283* @return : size of the Frame Header */
284static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
Yann Collet88fcd292015-11-25 14:42:45 +0100285{
Yann Collet03ea59b2016-03-12 01:25:40 +0100286 U32 fcsId;
287 if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);
288 fcsId = (((const BYTE*)src)[4]) >> 6;
289 return ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
Yann Collet88fcd292015-11-25 14:42:45 +0100290}
291
Yann Collet88fcd292015-11-25 14:42:45 +0100292
Yann Collet03ea59b2016-03-12 01:25:40 +0100293/** ZSTD_getFrameParams() :
294* decode Frame Header, or provide expected `srcSize`.
295* @return : 0, `fparamsPtr` is correctly filled,
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100296* >0, `srcSize` is too small, result is expected `srcSize`,
Yann Collet03ea59b2016-03-12 01:25:40 +0100297* or an error code, which can be tested using ZSTD_isError() */
Yann Collet09b21ee2016-03-15 12:56:03 +0100298size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize)
Yann Collet88fcd292015-11-25 14:42:45 +0100299{
Yann Collet03ea59b2016-03-12 01:25:40 +0100300 const BYTE* ip = (const BYTE*)src;
Yann Collet03ea59b2016-03-12 01:25:40 +0100301
302 if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_min;
Yann Colletd1b26842016-03-15 01:24:33 +0100303 if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
Yann Collet03ea59b2016-03-12 01:25:40 +0100304
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100305 /* ensure there is enough `srcSize` to fully read/decode frame header */
Yann Colletd1b26842016-03-15 01:24:33 +0100306 { size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize);
Yann Collet03ea59b2016-03-12 01:25:40 +0100307 if (srcSize < fhsize) return fhsize; }
308
Yann Collet0e491c02016-03-11 21:58:04 +0100309 memset(fparamsPtr, 0, sizeof(*fparamsPtr));
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100310 { BYTE const frameDesc = ip[4];
311 fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
312 fparamsPtr->mml = (frameDesc & 0x10) ? MINMATCH-1 : MINMATCH;
313 if ((frameDesc & 0x20) != 0) return ERROR(frameParameter_unsupported); /* reserved 1 bit */
314 switch(frameDesc >> 6) /* fcsId */
315 {
316 default: /* impossible */
317 case 0 : fparamsPtr->frameContentSize = 0; break;
318 case 1 : fparamsPtr->frameContentSize = ip[5]; break;
319 case 2 : fparamsPtr->frameContentSize = MEM_readLE16(ip+5)+256; break;
320 case 3 : fparamsPtr->frameContentSize = MEM_readLE64(ip+5); break;
321 } }
Yann Collet88fcd292015-11-25 14:42:45 +0100322 return 0;
323}
324
Yann Collet03ea59b2016-03-12 01:25:40 +0100325
326/** ZSTD_decodeFrameHeader() :
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100327* `srcSize` must be the size provided by ZSTD_frameHeaderSize().
Yann Collet01e5b952016-03-19 14:14:31 +0100328* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
Yann Collet03ea59b2016-03-12 01:25:40 +0100329static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* zc, const void* src, size_t srcSize)
Yann Collet26415d32015-11-26 12:43:28 +0100330{
Yann Collet03ea59b2016-03-12 01:25:40 +0100331 size_t result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
Yann Collet0e491c02016-03-11 21:58:04 +0100332 if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
Yann Collet00fd7a22015-11-28 16:03:22 +0100333 return result;
Yann Collet26415d32015-11-26 12:43:28 +0100334}
335
Yann Collet5be2dd22015-11-11 13:43:58 +0100336
Yann Collet01e5b952016-03-19 14:14:31 +0100337typedef struct
338{
339 blockType_t blockType;
340 U32 origSize;
341} blockProperties_t;
342
343/*! ZSTD_getcBlockSize() :
344* Provides the size of compressed block from block header `src` */
Yann Collet5be2dd22015-11-11 13:43:58 +0100345size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
346{
347 const BYTE* const in = (const BYTE* const)src;
Yann Collet01e5b952016-03-19 14:14:31 +0100348 size_t cSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100349
Yann Collet01e5b952016-03-19 14:14:31 +0100350 if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100351
Yann Collet01e5b952016-03-19 14:14:31 +0100352 bpPtr->blockType = (blockType_t)((*in) >> 6);
Yann Collet5be2dd22015-11-11 13:43:58 +0100353 cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
Yann Collet5be2dd22015-11-11 13:43:58 +0100354 bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
355
356 if (bpPtr->blockType == bt_end) return 0;
357 if (bpPtr->blockType == bt_rle) return 1;
358 return cSize;
359}
360
Yann Collet59d1f792016-01-23 19:28:41 +0100361
Yann Collet01e5b952016-03-19 14:14:31 +0100362static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100363{
Yann Collet01e5b952016-03-19 14:14:31 +0100364 if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);
Yann Collet5be2dd22015-11-11 13:43:58 +0100365 memcpy(dst, src, srcSize);
366 return srcSize;
367}
368
369
Yann Collet953ce722016-02-04 15:28:14 +0100370/*! ZSTD_decodeLiteralsBlock() :
Yann Collet14983e72015-11-11 21:38:21 +0100371 @return : nb of bytes read from src (< srcSize ) */
Yann Collet5b78d2f2015-11-12 15:36:05 +0100372size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
Yann Collet5be2dd22015-11-11 13:43:58 +0100373 const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
374{
Yann Collet5be2dd22015-11-11 13:43:58 +0100375 const BYTE* const istart = (const BYTE*) src;
376
377 /* any compressed block with literals segment must be at least this size */
378 if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
379
Yann Collet59d1f792016-01-23 19:28:41 +0100380 switch(istart[0]>> 6)
Yann Collet5be2dd22015-11-11 13:43:58 +0100381 {
Yann Collet59d1f792016-01-23 19:28:41 +0100382 case IS_HUF:
Yann Collet5be2dd22015-11-11 13:43:58 +0100383 {
Yann Colletafe07092016-01-25 04:10:46 +0100384 size_t litSize, litCSize, singleStream=0;
Yann Collet59d1f792016-01-23 19:28:41 +0100385 U32 lhSize = ((istart[0]) >> 4) & 3;
386 switch(lhSize)
387 {
388 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
389 /* 2 - 2 - 10 - 10 */
390 lhSize=3;
Yann Colletafe07092016-01-25 04:10:46 +0100391 singleStream = istart[0] & 16;
Yann Collet59d1f792016-01-23 19:28:41 +0100392 litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
393 litCSize = ((istart[1] & 3) << 8) + istart[2];
394 break;
395 case 2:
396 /* 2 - 2 - 14 - 14 */
397 lhSize=4;
398 litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);
399 litCSize = ((istart[2] & 63) << 8) + istart[3];
400 break;
401 case 3:
402 /* 2 - 2 - 18 - 18 */
403 lhSize=5;
404 litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);
405 litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];
406 break;
407 }
Yann Collet569b81a2016-03-16 15:26:51 +0100408 if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100409
Yann Colletafe07092016-01-25 04:10:46 +0100410 if (HUF_isError(singleStream ?
411 HUF_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :
412 HUF_decompress (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))
Yann Collet59d1f792016-01-23 19:28:41 +0100413 return ERROR(corruption_detected);
414
Yann Collet5be2dd22015-11-11 13:43:58 +0100415 dctx->litPtr = dctx->litBuffer;
Yann Collet569b81a2016-03-16 15:26:51 +0100416 dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+8;
Yann Collet5be2dd22015-11-11 13:43:58 +0100417 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100418 return litCSize + lhSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100419 }
Yann Colletb923f652016-01-26 03:14:20 +0100420 case IS_PCH:
421 {
422 size_t errorCode;
423 size_t litSize, litCSize;
424 U32 lhSize = ((istart[0]) >> 4) & 3;
425 if (lhSize != 1) /* only case supported for now : small litSize, single stream */
426 return ERROR(corruption_detected);
Yann Colletfb810d62016-01-28 00:18:06 +0100427 if (!dctx->flagStaticTables)
Yann Collet7b51a292016-01-26 15:58:49 +0100428 return ERROR(dictionary_corrupted);
Yann Colletb923f652016-01-26 03:14:20 +0100429
430 /* 2 - 2 - 10 - 10 */
431 lhSize=3;
432 litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
433 litCSize = ((istart[1] & 3) << 8) + istart[2];
434
435 errorCode = HUF_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
436 if (HUF_isError(errorCode)) return ERROR(corruption_detected);
437
438 dctx->litPtr = dctx->litBuffer;
Yann Collet569b81a2016-03-16 15:26:51 +0100439 dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH;
Yann Colletb923f652016-01-26 03:14:20 +0100440 dctx->litSize = litSize;
441 return litCSize + lhSize;
442 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100443 case IS_RAW:
444 {
Yann Collet59d1f792016-01-23 19:28:41 +0100445 size_t litSize;
446 U32 lhSize = ((istart[0]) >> 4) & 3;
447 switch(lhSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100448 {
Yann Collet59d1f792016-01-23 19:28:41 +0100449 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
450 lhSize=1;
451 litSize = istart[0] & 31;
452 break;
453 case 2:
454 litSize = ((istart[0] & 15) << 8) + istart[1];
455 break;
456 case 3:
457 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
458 break;
459 }
460
Yann Collet61e16ce2016-01-31 02:04:15 +0100461 if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
Yann Colletb010b3b2016-02-03 12:39:34 +0100462 if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100463 memcpy(dctx->litBuffer, istart+lhSize, litSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100464 dctx->litPtr = dctx->litBuffer;
Yann Collet569b81a2016-03-16 15:26:51 +0100465 dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+8;
Yann Collet5be2dd22015-11-11 13:43:58 +0100466 dctx->litSize = litSize;
Yann Colletbc4c8aa2016-01-25 17:26:01 +0100467 return lhSize+litSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100468 }
469 /* direct reference into compressed stream */
Yann Collet59d1f792016-01-23 19:28:41 +0100470 dctx->litPtr = istart+lhSize;
471 dctx->litBufSize = srcSize-lhSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100472 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100473 return lhSize+litSize;
474 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100475 case IS_RLE:
476 {
Yann Collet59d1f792016-01-23 19:28:41 +0100477 size_t litSize;
478 U32 lhSize = ((istart[0]) >> 4) & 3;
479 switch(lhSize)
480 {
481 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
482 lhSize = 1;
483 litSize = istart[0] & 31;
484 break;
485 case 2:
486 litSize = ((istart[0] & 15) << 8) + istart[1];
487 break;
488 case 3:
489 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
490 break;
491 }
Yann Collet569b81a2016-03-16 15:26:51 +0100492 if (litSize > ZSTD_BLOCKSIZE_MAX) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100493 memset(dctx->litBuffer, istart[lhSize], litSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100494 dctx->litPtr = dctx->litBuffer;
Yann Collet569b81a2016-03-16 15:26:51 +0100495 dctx->litBufSize = ZSTD_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH;
Yann Collet5be2dd22015-11-11 13:43:58 +0100496 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100497 return lhSize+1;
Yann Collet5be2dd22015-11-11 13:43:58 +0100498 }
Yann Colletb923f652016-01-26 03:14:20 +0100499 default:
500 return ERROR(corruption_detected); /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100501 }
502}
503
504
Yann Collet4db09ef2016-03-18 22:23:49 +0100505/*! ZSTD_buildSeqTable() :
506 @return : nb bytes read from src,
507 or an error code if it fails, testable with ZSTD_isError()
508*/
509static size_t ZSTD_buildSeqTable(FSE_DTable* DTable, U32 type, U32 rawBits, U32 maxLog,
510 const void* src, size_t srcSize)
511{
Yann Colletd1d210f2016-03-19 12:12:07 +0100512 U32 max = (1<<rawBits)-1;
Yann Collet4db09ef2016-03-18 22:23:49 +0100513 switch(type)
514 {
515 case FSE_ENCODING_RLE :
516 if (!srcSize) return ERROR(srcSize_wrong);
Yann Colletd1d210f2016-03-19 12:12:07 +0100517 FSE_buildDTable_rle(DTable, (*(const BYTE*)src) & max); /* if *src > max, data is corrupted */
Yann Collet4db09ef2016-03-18 22:23:49 +0100518 return 1;
519 case FSE_ENCODING_RAW :
520 FSE_buildDTable_raw(DTable, rawBits);
521 return 0;
522 case FSE_ENCODING_STATIC:
523 return 0;
524 default : /* impossible */
525 case FSE_ENCODING_DYNAMIC :
Yann Colletd1d210f2016-03-19 12:12:07 +0100526 { U32 tableLog;
Yann Collet4db09ef2016-03-18 22:23:49 +0100527 S16 norm[MaxSeq+1];
528 size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
529 if (FSE_isError(headerSize)) return ERROR(GENERIC);
530 if (tableLog > maxLog) return ERROR(corruption_detected);
531 FSE_buildDTable(DTable, norm, max, tableLog);
532 return headerSize;
533 } }
534}
535
536
Yann Collet5be2dd22015-11-11 13:43:58 +0100537size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
538 FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
539 const void* src, size_t srcSize)
540{
541 const BYTE* const istart = (const BYTE* const)src;
542 const BYTE* ip = istart;
543 const BYTE* const iend = istart + srcSize;
544 U32 LLtype, Offtype, MLtype;
Yann Collet5be2dd22015-11-11 13:43:58 +0100545
546 /* check */
Yann Collet4db09ef2016-03-18 22:23:49 +0100547 if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100548
549 /* SeqHead */
Yann Collet61e16ce2016-01-31 02:04:15 +0100550 *nbSeq = *ip++;
551 if (*nbSeq==0) return 1;
Yann Colletd409db62016-03-04 14:45:31 +0100552 if (*nbSeq >= 0x7F) {
553 if (*nbSeq == 0xFF)
554 *nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
555 else
556 *nbSeq = ((nbSeq[0]-0x80)<<8) + *ip++;
557 }
Yann Collete93d6ce2016-01-31 00:58:06 +0100558
Yann Colletd409db62016-03-04 14:45:31 +0100559 /* FSE table descriptors */
Yann Collet5be2dd22015-11-11 13:43:58 +0100560 LLtype = *ip >> 6;
561 Offtype = (*ip >> 4) & 3;
562 MLtype = (*ip >> 2) & 3;
Yann Collet4db09ef2016-03-18 22:23:49 +0100563 { size_t dumpsLength;
564 if (*ip & 2) {
565 dumpsLength = ip[2];
566 dumpsLength += ip[1] << 8;
567 ip += 3;
568 } else {
569 dumpsLength = ip[1];
570 dumpsLength += (ip[0] & 1) << 8;
571 ip += 2;
572 }
573 *dumpsPtr = ip;
574 ip += dumpsLength;
575 *dumpsLengthPtr = dumpsLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100576 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100577
578 /* check */
579 if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
580
Yann Collet39c596c2016-03-18 21:40:56 +0100581 /* Build DTables */
Yann Collet4db09ef2016-03-18 22:23:49 +0100582 { size_t const bhSize = ZSTD_buildSeqTable(DTableLL, LLtype, LLbits, LLFSELog, ip, iend-ip);
583 if (ZSTD_isError(bhSize)) return ERROR(corruption_detected);
584 ip += bhSize;
585 }
586 { size_t const bhSize = ZSTD_buildSeqTable(DTableOffb, Offtype, Offbits, OffFSELog, ip, iend-ip);
587 if (ZSTD_isError(bhSize)) return ERROR(corruption_detected);
588 ip += bhSize;
589 }
590 { size_t const bhSize = ZSTD_buildSeqTable(DTableML, MLtype, MLbits, MLFSELog, ip, iend-ip);
591 if (ZSTD_isError(bhSize)) return ERROR(corruption_detected);
592 ip += bhSize;
593 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100594
595 return ip-istart;
596}
597
598
599typedef struct {
600 size_t litLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100601 size_t matchLength;
Yann Collete93d6ce2016-01-31 00:58:06 +0100602 size_t offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100603} seq_t;
604
605typedef struct {
606 BIT_DStream_t DStream;
607 FSE_DState_t stateLL;
608 FSE_DState_t stateOffb;
609 FSE_DState_t stateML;
610 size_t prevOffset;
611 const BYTE* dumps;
612 const BYTE* dumpsEnd;
613} seqState_t;
614
inikepe9f30ea2016-02-03 12:53:07 +0100615
inikep6b3739c2016-02-22 15:53:42 +0100616static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
Yann Collet5be2dd22015-11-11 13:43:58 +0100617{
Yann Collet5be2dd22015-11-11 13:43:58 +0100618 const BYTE* dumps = seqState->dumps;
619 const BYTE* const de = seqState->dumpsEnd;
Yann Collet3fd164e2016-03-17 12:56:46 +0100620 size_t litLength, offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100621
622 /* Literal length */
Yann Collete93d6ce2016-01-31 00:58:06 +0100623 litLength = FSE_peakSymbol(&(seqState->stateLL));
Yann Colletfb810d62016-01-28 00:18:06 +0100624 if (litLength == MaxLL) {
Yann Collet3fd164e2016-03-17 12:56:46 +0100625 const U32 add = *dumps++;
Yann Collet5be2dd22015-11-11 13:43:58 +0100626 if (add < 255) litLength += add;
Yann Colletfb810d62016-01-28 00:18:06 +0100627 else {
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100628 litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no risk : dumps is always followed by seq tables > 1 byte */
629 if (litLength&1) litLength>>=1, dumps += 3;
630 else litLength = (U16)(litLength)>>1, dumps += 2;
Yann Collet5be2dd22015-11-11 13:43:58 +0100631 }
632 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
633 }
634
635 /* Offset */
Yann Colletd1d210f2016-03-19 12:12:07 +0100636 { static const U32 offsetPrefix[MaxOff+1] = {
637 1 /*fake*/, 1, 2, 4, 8, 0x10, 0x20, 0x40,
638 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000,
639 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000,
640 0x800000, 0x1000000, 0x2000000, 0x4000000, /*fake*/ 1, 1, 1, 1 };
641 U32 const offsetCode = FSE_peakSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
642 U32 const nbBits = offsetCode ? offsetCode-1 : 0;
Yann Collet5be2dd22015-11-11 13:43:58 +0100643 offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);
644 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
Yann Colletb40287a2016-03-17 12:11:16 +0100645 if (offsetCode==0) offset = litLength ? seq->offset : seqState->prevOffset;
Yann Collet55aa7f92015-11-20 12:04:52 +0100646 if (offsetCode | !litLength) seqState->prevOffset = seq->offset; /* cmove */
Yann Collete93d6ce2016-01-31 00:58:06 +0100647 FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* update */
Yann Collet5be2dd22015-11-11 13:43:58 +0100648 }
649
Yann Collete93d6ce2016-01-31 00:58:06 +0100650 /* Literal length update */
651 FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); /* update */
652 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
653
Yann Collet5be2dd22015-11-11 13:43:58 +0100654 /* MatchLength */
Yann Collet01e5b952016-03-19 14:14:31 +0100655 { size_t matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
Yann Collet3fd164e2016-03-17 12:56:46 +0100656 if (matchLength == MaxML) {
657 const U32 add = *dumps++;
658 if (add < 255) matchLength += add;
659 else {
660 matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
661 if (matchLength&1) matchLength>>=1, dumps += 3;
662 else matchLength = (U16)(matchLength)>>1, dumps += 2;
663 }
664 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
Yann Collet5be2dd22015-11-11 13:43:58 +0100665 }
Yann Collet3fd164e2016-03-17 12:56:46 +0100666 matchLength += mls;
667 seq->matchLength = matchLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100668 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100669
670 /* save result */
671 seq->litLength = litLength;
672 seq->offset = offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100673 seqState->dumps = dumps;
Yann Colletfb810d62016-01-28 00:18:06 +0100674
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100675#if 0 /* debug */
Yann Colletfb810d62016-01-28 00:18:06 +0100676 {
677 static U64 totalDecoded = 0;
678 printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
679 (U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);
680 totalDecoded += litLength + matchLength;
681 }
682#endif
Yann Collet5be2dd22015-11-11 13:43:58 +0100683}
684
685
Yann Collet5b78d2f2015-11-12 15:36:05 +0100686FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
Yann Colletb3a2af92015-11-19 17:13:19 +0100687 BYTE* const oend, seq_t sequence,
Yann Collet5be2dd22015-11-11 13:43:58 +0100688 const BYTE** litPtr, const BYTE* const litLimit_8,
Yann Collet417890c2015-12-04 17:16:37 +0100689 const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
Yann Collet5be2dd22015-11-11 13:43:58 +0100690{
Yann Colletb3a2af92015-11-19 17:13:19 +0100691 static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
692 static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
Yann Collet5be2dd22015-11-11 13:43:58 +0100693 BYTE* const oLitEnd = op + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100694 const size_t sequenceLength = sequence.litLength + sequence.matchLength;
695 BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
Yann Collet5be2dd22015-11-11 13:43:58 +0100696 BYTE* const oend_8 = oend-8;
697 const BYTE* const litEnd = *litPtr + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100698 const BYTE* match = oLitEnd - sequence.offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100699
700 /* check */
701 if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
702 if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
703 if (litEnd > litLimit_8) return ERROR(corruption_detected); /* risk read beyond lit buffer */
704
705 /* copy Literals */
706 ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
707 op = oLitEnd;
708 *litPtr = litEnd; /* update for next sequence */
709
710 /* copy Match */
Yann Collet7b51a292016-01-26 15:58:49 +0100711 if (sequence.offset > (size_t)(oLitEnd - base)) {
Yann Collet44287a32015-11-30 23:13:56 +0100712 /* offset beyond prefix */
Yann Collet9f5ab1a2015-12-11 00:27:41 +0100713 if (sequence.offset > (size_t)(oLitEnd - vBase))
714 return ERROR(corruption_detected);
Yann Collet44287a32015-11-30 23:13:56 +0100715 match = dictEnd - (base-match);
Yann Collet7b51a292016-01-26 15:58:49 +0100716 if (match + sequence.matchLength <= dictEnd) {
Yann Collet4bfe4152015-12-06 13:18:37 +0100717 memmove(oLitEnd, match, sequence.matchLength);
Yann Collet44287a32015-11-30 23:13:56 +0100718 return sequenceLength;
719 }
720 /* span extDict & currentPrefixSegment */
Yann Colletd1d210f2016-03-19 12:12:07 +0100721 { size_t const length1 = dictEnd - match;
Yann Collet4bfe4152015-12-06 13:18:37 +0100722 memmove(oLitEnd, match, length1);
Yann Collet44287a32015-11-30 23:13:56 +0100723 op = oLitEnd + length1;
724 sequence.matchLength -= length1;
725 match = base;
Yann Colletfb810d62016-01-28 00:18:06 +0100726 } }
Yann Collet0f366c62015-11-12 16:19:30 +0100727
Yann Collet44287a32015-11-30 23:13:56 +0100728 /* match within prefix */
Yann Collet7b51a292016-01-26 15:58:49 +0100729 if (sequence.offset < 8) {
Yann Collet44287a32015-11-30 23:13:56 +0100730 /* close range match, overlap */
731 const int sub2 = dec64table[sequence.offset];
732 op[0] = match[0];
733 op[1] = match[1];
734 op[2] = match[2];
735 op[3] = match[3];
736 match += dec32table[sequence.offset];
737 ZSTD_copy4(op+4, match);
738 match -= sub2;
Yann Colletfb810d62016-01-28 00:18:06 +0100739 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100740 ZSTD_copy8(op, match);
741 }
742 op += 8; match += 8;
Yann Collet5be2dd22015-11-11 13:43:58 +0100743
inikepa4dde252016-03-01 14:14:35 +0100744 if (oMatchEnd > oend-(16-3)) { // 3 = MINMATCH
Yann Collet7b51a292016-01-26 15:58:49 +0100745 if (op < oend_8) {
Yann Collet44287a32015-11-30 23:13:56 +0100746 ZSTD_wildcopy(op, match, oend_8 - op);
747 match += oend_8 - op;
748 op = oend_8;
749 }
Yann Collet01e5b952016-03-19 14:14:31 +0100750 while (op < oMatchEnd) *op++ = *match++;
Yann Colletfb810d62016-01-28 00:18:06 +0100751 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100752 ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
753 }
754 return sequenceLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100755}
756
Yann Colletb3a2af92015-11-19 17:13:19 +0100757
Yann Collet5be2dd22015-11-11 13:43:58 +0100758static size_t ZSTD_decompressSequences(
Yann Collet5b78d2f2015-11-12 15:36:05 +0100759 ZSTD_DCtx* dctx,
Yann Collet5be2dd22015-11-11 13:43:58 +0100760 void* dst, size_t maxDstSize,
761 const void* seqStart, size_t seqSize)
762{
Yann Collet5be2dd22015-11-11 13:43:58 +0100763 const BYTE* ip = (const BYTE*)seqStart;
764 const BYTE* const iend = ip + seqSize;
765 BYTE* const ostart = (BYTE* const)dst;
766 BYTE* op = ostart;
767 BYTE* const oend = ostart + maxDstSize;
768 size_t errorCode, dumpsLength;
769 const BYTE* litPtr = dctx->litPtr;
770 const BYTE* const litLimit_8 = litPtr + dctx->litBufSize - 8;
771 const BYTE* const litEnd = litPtr + dctx->litSize;
772 int nbSeq;
773 const BYTE* dumps;
774 U32* DTableLL = dctx->LLTable;
775 U32* DTableML = dctx->MLTable;
776 U32* DTableOffb = dctx->OffTable;
Yann Collet417890c2015-12-04 17:16:37 +0100777 const BYTE* const base = (const BYTE*) (dctx->base);
778 const BYTE* const vBase = (const BYTE*) (dctx->vBase);
779 const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
Yann Collet0e491c02016-03-11 21:58:04 +0100780 const U32 mls = dctx->fParams.mml;
Yann Collet5be2dd22015-11-11 13:43:58 +0100781
782 /* Build Decoding Tables */
783 errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
784 DTableLL, DTableML, DTableOffb,
Yann Colletfb810d62016-01-28 00:18:06 +0100785 ip, seqSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100786 if (ZSTD_isError(errorCode)) return errorCode;
787 ip += errorCode;
788
789 /* Regen sequences */
Yann Collete93d6ce2016-01-31 00:58:06 +0100790 if (nbSeq) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100791 seq_t sequence;
792 seqState_t seqState;
793
794 memset(&sequence, 0, sizeof(sequence));
Yann Collet61e16ce2016-01-31 02:04:15 +0100795 sequence.offset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100796 seqState.dumps = dumps;
797 seqState.dumpsEnd = dumps + dumpsLength;
Yann Collet61e16ce2016-01-31 02:04:15 +0100798 seqState.prevOffset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100799 errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
800 if (ERR_isError(errorCode)) return ERROR(corruption_detected);
801 FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
802 FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
803 FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
804
Yann Collet7b51a292016-01-26 15:58:49 +0100805 for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
Yann Colletb3a2af92015-11-19 17:13:19 +0100806 size_t oneSeqSize;
807 nbSeq--;
inikep6b3739c2016-02-22 15:53:42 +0100808 ZSTD_decodeSequence(&sequence, &seqState, mls);
Yann Colletb3a2af92015-11-19 17:13:19 +0100809 oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_8, base, vBase, dictEnd);
Yann Collet370b08e2016-03-08 00:03:59 +0100810 if (ZSTD_isError(oneSeqSize))
811 return oneSeqSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100812 op += oneSeqSize;
813 }
814
815 /* check if reached exact end */
Yann Collet35f7de52016-01-31 02:51:03 +0100816 if (nbSeq) return ERROR(corruption_detected);
Yann Collete93d6ce2016-01-31 00:58:06 +0100817 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100818
Yann Collete93d6ce2016-01-31 00:58:06 +0100819 /* last literal segment */
Yann Collet01e5b952016-03-19 14:14:31 +0100820 { size_t const lastLLSize = litEnd - litPtr;
Yann Collete93d6ce2016-01-31 00:58:06 +0100821 if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */
822 if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
823 memcpy(op, litPtr, lastLLSize);
824 op += lastLLSize;
825 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100826
827 return op-ostart;
828}
829
830
Yann Colletb0125102016-01-09 02:00:10 +0100831static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
832{
Yann Collet7b51a292016-01-26 15:58:49 +0100833 if (dst != dctx->previousDstEnd) { /* not contiguous */
Yann Colletb0125102016-01-09 02:00:10 +0100834 dctx->dictEnd = dctx->previousDstEnd;
835 dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
836 dctx->base = dst;
837 dctx->previousDstEnd = dst;
838 }
839}
840
841
842static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100843 void* dst, size_t dstCapacity,
Yann Collet5be2dd22015-11-11 13:43:58 +0100844 const void* src, size_t srcSize)
Yann Colletb010b3b2016-02-03 12:39:34 +0100845{ /* blockType == blockCompressed */
Yann Collet5be2dd22015-11-11 13:43:58 +0100846 const BYTE* ip = (const BYTE*)src;
Yann Colletb010b3b2016-02-03 12:39:34 +0100847 size_t litCSize;
848
Yann Collet569b81a2016-03-16 15:26:51 +0100849 if (srcSize >= ZSTD_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100850
inikepa4dde252016-03-01 14:14:35 +0100851 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBlock_internal searchLength=%d\n", dctx->base, dctx->params.searchLength);
852
Yann Collet5be2dd22015-11-11 13:43:58 +0100853 /* Decode literals sub-block */
Yann Colletb010b3b2016-02-03 12:39:34 +0100854 litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100855 if (ZSTD_isError(litCSize)) return litCSize;
856 ip += litCSize;
857 srcSize -= litCSize;
858
Yann Colletb010b3b2016-02-03 12:39:34 +0100859 return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100860}
861
862
Yann Colletb0125102016-01-09 02:00:10 +0100863size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100864 void* dst, size_t dstCapacity,
Yann Colletb0125102016-01-09 02:00:10 +0100865 const void* src, size_t srcSize)
866{
867 ZSTD_checkContinuity(dctx, dst);
Yann Colletb010b3b2016-02-03 12:39:34 +0100868 return ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
Yann Colletb0125102016-01-09 02:00:10 +0100869}
870
871
Yann Collet0e491c02016-03-11 21:58:04 +0100872/*! ZSTD_decompress_continueDCtx() :
873* `dctx` must have been properly initialized */
874static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
Yann Collet01e5b952016-03-19 14:14:31 +0100875 void* dst, size_t dstCapacity,
Yann Collet7b51a292016-01-26 15:58:49 +0100876 const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100877{
878 const BYTE* ip = (const BYTE*)src;
879 const BYTE* iend = ip + srcSize;
880 BYTE* const ostart = (BYTE* const)dst;
881 BYTE* op = ostart;
Yann Collet01e5b952016-03-19 14:14:31 +0100882 BYTE* const oend = ostart + dstCapacity;
Yann Collet5be2dd22015-11-11 13:43:58 +0100883 size_t remainingSize = srcSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100884 blockProperties_t blockProperties;
885
Yann Collet01e5b952016-03-19 14:14:31 +0100886 /* check */
887 if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100888#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
Yann Collet01e5b952016-03-19 14:14:31 +0100889 { const U32 magicNumber = MEM_readLE32(src);
890 if (ZSTD_isLegacy(magicNumber))
891 return ZSTD_decompressLegacy(dst, dstCapacity, src, srcSize, magicNumber);
892 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100893#endif
Yann Collet01e5b952016-03-19 14:14:31 +0100894
895 /* Frame Header */
896 { size_t const frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
Yann Collet88fcd292015-11-25 14:42:45 +0100897 if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
898 if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
Yann Collet01e5b952016-03-19 14:14:31 +0100899 if (ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);
Yann Collet88fcd292015-11-25 14:42:45 +0100900 ip += frameHeaderSize; remainingSize -= frameHeaderSize;
Yann Collet88fcd292015-11-25 14:42:45 +0100901 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100902
903 /* Loop on each block */
Yann Collet01e5b952016-03-19 14:14:31 +0100904 while (1) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100905 size_t decodedSize=0;
906 size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
907 if (ZSTD_isError(cBlockSize)) return cBlockSize;
908
909 ip += ZSTD_blockHeaderSize;
910 remainingSize -= ZSTD_blockHeaderSize;
911 if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
912
913 switch(blockProperties.blockType)
914 {
915 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +0100916 decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100917 break;
918 case bt_raw :
Yann Collet0f366c62015-11-12 16:19:30 +0100919 decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100920 break;
921 case bt_rle :
922 return ERROR(GENERIC); /* not yet supported */
923 break;
924 case bt_end :
925 /* end of frame */
926 if (remainingSize) return ERROR(srcSize_wrong);
927 break;
928 default:
929 return ERROR(GENERIC); /* impossible */
930 }
931 if (cBlockSize == 0) break; /* bt_end */
932
933 if (ZSTD_isError(decodedSize)) return decodedSize;
934 op += decodedSize;
935 ip += cBlockSize;
936 remainingSize -= cBlockSize;
937 }
938
939 return op-ostart;
940}
941
Yann Collet31683c02015-12-18 01:26:48 +0100942
Yann Collet7b51a292016-01-26 15:58:49 +0100943size_t ZSTD_decompress_usingPreparedDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* refDCtx,
Yann Collet01e5b952016-03-19 14:14:31 +0100944 void* dst, size_t dstCapacity,
Yann Collet7b51a292016-01-26 15:58:49 +0100945 const void* src, size_t srcSize)
946{
947 ZSTD_copyDCtx(dctx, refDCtx);
948 ZSTD_checkContinuity(dctx, dst);
Yann Collet01e5b952016-03-19 14:14:31 +0100949 return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
Yann Collet7b51a292016-01-26 15:58:49 +0100950}
951
952
953size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
Yann Collet01e5b952016-03-19 14:14:31 +0100954 void* dst, size_t dstCapacity,
Yann Collet7b51a292016-01-26 15:58:49 +0100955 const void* src, size_t srcSize,
956 const void* dict, size_t dictSize)
957{
958 ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
inikepa4dde252016-03-01 14:14:35 +0100959 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin_usingDict searchLength=%d\n", dctx->base, dctx->params.searchLength);
Yann Collet7b51a292016-01-26 15:58:49 +0100960 ZSTD_checkContinuity(dctx, dst);
Yann Collet01e5b952016-03-19 14:14:31 +0100961 return ZSTD_decompressFrame(dctx, dst, dstCapacity, src, srcSize);
Yann Collet7b51a292016-01-26 15:58:49 +0100962}
963
964
Yann Collet01e5b952016-03-19 14:14:31 +0100965size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet31683c02015-12-18 01:26:48 +0100966{
Yann Collet01e5b952016-03-19 14:14:31 +0100967 return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
Yann Collet31683c02015-12-18 01:26:48 +0100968}
969
Yann Collet0e491c02016-03-11 21:58:04 +0100970
Yann Collet01e5b952016-03-19 14:14:31 +0100971size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100972{
Yann Collet3a3b72f2016-01-11 12:56:11 +0100973#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
974 size_t regenSize;
975 ZSTD_DCtx* dctx = ZSTD_createDCtx();
976 if (dctx==NULL) return ERROR(memory_allocation);
Yann Collet01e5b952016-03-19 14:14:31 +0100977 regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
Yann Collet3a3b72f2016-01-11 12:56:11 +0100978 ZSTD_freeDCtx(dctx);
979 return regenSize;
980#else
Yann Collet31683c02015-12-18 01:26:48 +0100981 ZSTD_DCtx dctx;
Yann Collet01e5b952016-03-19 14:14:31 +0100982 return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
Yann Colleta768a302016-01-21 16:04:35 +0100983#endif
Yann Collet5be2dd22015-11-11 13:43:58 +0100984}
985
986
Yann Collet346bffb2016-03-15 15:24:52 +0100987/*_******************************
Yann Collet5be2dd22015-11-11 13:43:58 +0100988* Streaming Decompression API
989********************************/
Yann Collet5be2dd22015-11-11 13:43:58 +0100990size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)
991{
992 return dctx->expected;
993}
994
Yann Collet37422192016-01-25 16:54:05 +0100995size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100996{
997 /* Sanity check */
Yann Collet37422192016-01-25 16:54:05 +0100998 if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
999 ZSTD_checkContinuity(dctx, dst);
Yann Collet5be2dd22015-11-11 13:43:58 +01001000
Yann Collet88fcd292015-11-25 14:42:45 +01001001 /* Decompress : frame header; part 1 */
Yann Collet37422192016-01-25 16:54:05 +01001002 switch (dctx->stage)
Yann Collet5be2dd22015-11-11 13:43:58 +01001003 {
Yann Collet88fcd292015-11-25 14:42:45 +01001004 case ZSTDds_getFrameHeaderSize :
Yann Collet5be2dd22015-11-11 13:43:58 +01001005 {
Yann Collet88fcd292015-11-25 14:42:45 +01001006 /* get frame header size */
1007 if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
Yann Collet03ea59b2016-03-12 01:25:40 +01001008 dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
Yann Collet37422192016-01-25 16:54:05 +01001009 if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
1010 memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
Yann Collet7b51a292016-01-26 15:58:49 +01001011 if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
Yann Collet37422192016-01-25 16:54:05 +01001012 dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_min;
1013 dctx->stage = ZSTDds_decodeFrameHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001014 return 0;
1015 }
Yann Collet37422192016-01-25 16:54:05 +01001016 dctx->expected = 0; /* not necessary to copy more */
Yann Collet5be2dd22015-11-11 13:43:58 +01001017 }
Yann Collet88fcd292015-11-25 14:42:45 +01001018 case ZSTDds_decodeFrameHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001019 {
Yann Collet88fcd292015-11-25 14:42:45 +01001020 /* get frame header */
1021 size_t result;
Yann Collet37422192016-01-25 16:54:05 +01001022 memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
Yann Collet03ea59b2016-03-12 01:25:40 +01001023 result = ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001024 if (ZSTD_isError(result)) return result;
Yann Collet37422192016-01-25 16:54:05 +01001025 dctx->expected = ZSTD_blockHeaderSize;
1026 dctx->stage = ZSTDds_decodeBlockHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001027 return 0;
Yann Collet5be2dd22015-11-11 13:43:58 +01001028 }
Yann Collet88fcd292015-11-25 14:42:45 +01001029 case ZSTDds_decodeBlockHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001030 {
Yann Collet88fcd292015-11-25 14:42:45 +01001031 /* Decode block header */
1032 blockProperties_t bp;
1033 size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
1034 if (ZSTD_isError(blockSize)) return blockSize;
Yann Collet7b51a292016-01-26 15:58:49 +01001035 if (bp.blockType == bt_end) {
Yann Collet37422192016-01-25 16:54:05 +01001036 dctx->expected = 0;
1037 dctx->stage = ZSTDds_getFrameHeaderSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001038 }
Yann Collet7b51a292016-01-26 15:58:49 +01001039 else {
Yann Collet37422192016-01-25 16:54:05 +01001040 dctx->expected = blockSize;
1041 dctx->bType = bp.blockType;
1042 dctx->stage = ZSTDds_decompressBlock;
Yann Collet88fcd292015-11-25 14:42:45 +01001043 }
Yann Collet88fcd292015-11-25 14:42:45 +01001044 return 0;
1045 }
Yann Collet417890c2015-12-04 17:16:37 +01001046 case ZSTDds_decompressBlock:
Yann Collet88fcd292015-11-25 14:42:45 +01001047 {
1048 /* Decompress : block content */
1049 size_t rSize;
Yann Collet37422192016-01-25 16:54:05 +01001050 switch(dctx->bType)
Yann Collet88fcd292015-11-25 14:42:45 +01001051 {
1052 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +01001053 rSize = ZSTD_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001054 break;
1055 case bt_raw :
1056 rSize = ZSTD_copyRawBlock(dst, maxDstSize, src, srcSize);
1057 break;
1058 case bt_rle :
1059 return ERROR(GENERIC); /* not yet handled */
1060 break;
1061 case bt_end : /* should never happen (filtered at phase 1) */
1062 rSize = 0;
1063 break;
1064 default:
Yann Collet7b51a292016-01-26 15:58:49 +01001065 return ERROR(GENERIC); /* impossible */
Yann Collet88fcd292015-11-25 14:42:45 +01001066 }
Yann Collet37422192016-01-25 16:54:05 +01001067 dctx->stage = ZSTDds_decodeBlockHeader;
1068 dctx->expected = ZSTD_blockHeaderSize;
1069 dctx->previousDstEnd = (char*)dst + rSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001070 return rSize;
1071 }
1072 default:
1073 return ERROR(GENERIC); /* impossible */
1074 }
Yann Collet5be2dd22015-11-11 13:43:58 +01001075}
1076
1077
Yann Colletb923f652016-01-26 03:14:20 +01001078static void ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Collet417890c2015-12-04 17:16:37 +01001079{
Yann Collet37422192016-01-25 16:54:05 +01001080 dctx->dictEnd = dctx->previousDstEnd;
1081 dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
1082 dctx->base = dict;
1083 dctx->previousDstEnd = (const char*)dict + dictSize;
Yann Collet417890c2015-12-04 17:16:37 +01001084}
Yann Colletb923f652016-01-26 03:14:20 +01001085
Yann Colletb923f652016-01-26 03:14:20 +01001086static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1087{
Yann Colletfb810d62016-01-28 00:18:06 +01001088 size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;
1089 short offcodeNCount[MaxOff+1];
1090 U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
1091 short matchlengthNCount[MaxML+1];
1092 unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
1093 short litlengthNCount[MaxLL+1];
1094 unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
1095
1096 hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize);
Yann Colletb923f652016-01-26 03:14:20 +01001097 if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
Yann Colletfb810d62016-01-28 00:18:06 +01001098 dict = (const char*)dict + hSize;
1099 dictSize -= hSize;
1100
1101 offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
1102 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
1103 errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
1104 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1105 dict = (const char*)dict + offcodeHeaderSize;
1106 dictSize -= offcodeHeaderSize;
1107
1108 matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
1109 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
1110 errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
1111 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1112 dict = (const char*)dict + matchlengthHeaderSize;
1113 dictSize -= matchlengthHeaderSize;
1114
1115 litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
1116 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
1117 errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
1118 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1119
1120 dctx->flagStaticTables = 1;
1121 return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
Yann Colletb923f652016-01-26 03:14:20 +01001122}
1123
Yann Collet7b51a292016-01-26 15:58:49 +01001124static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Colletb923f652016-01-26 03:14:20 +01001125{
1126 size_t eSize;
1127 U32 magic = MEM_readLE32(dict);
1128 if (magic != ZSTD_DICT_MAGIC) {
1129 /* pure content mode */
1130 ZSTD_refDictContent(dctx, dict, dictSize);
1131 return 0;
1132 }
1133 /* load entropy tables */
1134 dict = (const char*)dict + 4;
1135 dictSize -= 4;
1136 eSize = ZSTD_loadEntropy(dctx, dict, dictSize);
1137 if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
1138
1139 /* reference dictionary content */
1140 dict = (const char*)dict + eSize;
1141 dictSize -= eSize;
1142 ZSTD_refDictContent(dctx, dict, dictSize);
1143
1144 return 0;
1145}
1146
Yann Collet7b51a292016-01-26 15:58:49 +01001147
1148size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1149{
1150 size_t errorCode;
1151 errorCode = ZSTD_decompressBegin(dctx);
1152 if (ZSTD_isError(errorCode)) return errorCode;
1153
1154 if (dict && dictSize) {
1155 errorCode = ZSTD_decompress_insertDictionary(dctx, dict, dictSize);
1156 if (ZSTD_isError(errorCode)) return ERROR(dictionary_corrupted);
1157 }
1158
1159 return 0;
1160}
1161