blob: 685e6de444e243ddfe24b22526e8398f3674eaf8 [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 :
29 - zstd source repository : https://github.com/Cyan4973/zstd
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 Colletfb810d62016-01-28 00:18:06 +010087/*-*************************************
Yann Collet14983e72015-11-11 21:38:21 +010088* Local types
89***************************************/
90typedef struct
91{
92 blockType_t blockType;
93 U32 origSize;
94} blockProperties_t;
Yann Collet5be2dd22015-11-11 13:43:58 +010095
96
Yann Collet03ea59b2016-03-12 01:25:40 +010097/*_*******************************************************
Yann Collet5be2dd22015-11-11 13:43:58 +010098* Memory operations
99**********************************************************/
100static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
101
102
Yann Collet03ea59b2016-03-12 01:25:40 +0100103/*-*************************************
Yann Collet5be2dd22015-11-11 13:43:58 +0100104* Error Management
105***************************************/
Yann Collet14983e72015-11-11 21:38:21 +0100106unsigned ZSTD_versionNumber (void) { return ZSTD_VERSION_NUMBER; }
107
Yann Collet953ce722016-02-04 15:28:14 +0100108/*! ZSTD_isError() :
Yann Collet5be2dd22015-11-11 13:43:58 +0100109* tells if a return value is an error code */
110unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
111
Yann Collet953ce722016-02-04 15:28:14 +0100112/*! ZSTD_getError() :
Yann Collet72bff502016-02-03 12:06:24 +0100113* convert a `size_t` function result into a proper ZSTD_errorCode enum */
Yann Collet982ffc72016-02-05 02:33:10 +0100114ZSTD_ErrorCode ZSTD_getError(size_t code) { return ERR_getError(code); }
Yann Collet72bff502016-02-03 12:06:24 +0100115
Yann Collet953ce722016-02-04 15:28:14 +0100116/*! ZSTD_getErrorName() :
Yann Collet5be2dd22015-11-11 13:43:58 +0100117* provides error code string (useful for debugging) */
118const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }
119
120
Yann Collet03ea59b2016-03-12 01:25:40 +0100121/*-*************************************************************
Yann Collet5b78d2f2015-11-12 15:36:05 +0100122* Context management
Yann Collet5be2dd22015-11-11 13:43:58 +0100123***************************************************************/
Yann Collete4fdad52015-11-25 21:09:17 +0100124typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
Yann Collet88fcd292015-11-25 14:42:45 +0100125 ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTD_dStage;
126
Yann Collet5be2dd22015-11-11 13:43:58 +0100127struct ZSTD_DCtx_s
128{
Yann Colletfb810d62016-01-28 00:18:06 +0100129 FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
130 FSE_DTable OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
131 FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
132 unsigned hufTableX4[HUF_DTABLE_SIZE(HufLog)];
Yann Collet417890c2015-12-04 17:16:37 +0100133 const void* previousDstEnd;
134 const void* base;
135 const void* vBase;
136 const void* dictEnd;
Yann Collet5be2dd22015-11-11 13:43:58 +0100137 size_t expected;
Yann Collet88fcd292015-11-25 14:42:45 +0100138 size_t headerSize;
Yann Collet0e491c02016-03-11 21:58:04 +0100139 ZSTD_frameParams fParams;
Yann Colletfb810d62016-01-28 00:18:06 +0100140 blockType_t bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
Yann Collet88fcd292015-11-25 14:42:45 +0100141 ZSTD_dStage stage;
Yann Colletfb810d62016-01-28 00:18:06 +0100142 U32 flagStaticTables;
Yann Collet5be2dd22015-11-11 13:43:58 +0100143 const BYTE* litPtr;
144 size_t litBufSize;
145 size_t litSize;
Yann Colletb923f652016-01-26 03:14:20 +0100146 BYTE litBuffer[BLOCKSIZE + WILDCOPY_OVERLENGTH];
Yann Collet0e491c02016-03-11 21:58:04 +0100147 BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
Yann Collet417890c2015-12-04 17:16:37 +0100148}; /* typedef'd to ZSTD_DCtx within "zstd_static.h" */
Yann Collet5be2dd22015-11-11 13:43:58 +0100149
Yann Colletfb810d62016-01-28 00:18:06 +0100150size_t sizeofDCtx (void) { return sizeof(ZSTD_DCtx); }
151
Yann Collet7b51a292016-01-26 15:58:49 +0100152size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
Yann Collet5b78d2f2015-11-12 15:36:05 +0100153{
Yann Collet88fcd292015-11-25 14:42:45 +0100154 dctx->expected = ZSTD_frameHeaderSize_min;
155 dctx->stage = ZSTDds_getFrameHeaderSize;
Yann Collet5b78d2f2015-11-12 15:36:05 +0100156 dctx->previousDstEnd = NULL;
157 dctx->base = NULL;
158 dctx->vBase = NULL;
159 dctx->dictEnd = NULL;
Yann Colletb923f652016-01-26 03:14:20 +0100160 dctx->hufTableX4[0] = HufLog;
Yann Colletfb810d62016-01-28 00:18:06 +0100161 dctx->flagStaticTables = 0;
Yann Collet0e491c02016-03-11 21:58:04 +0100162 dctx->fParams.mml = MINMATCH; /* overwritten by frame but forces ZSTD_btopt to MINMATCH in block mode */
inikepa4dde252016-03-01 14:14:35 +0100163 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin searchLength=%d\n", dctx->base, dctx->params.searchLength);
Yann Collet5b78d2f2015-11-12 15:36:05 +0100164 return 0;
165}
166
167ZSTD_DCtx* ZSTD_createDCtx(void)
168{
169 ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));
170 if (dctx==NULL) return NULL;
Yann Collet7b51a292016-01-26 15:58:49 +0100171 ZSTD_decompressBegin(dctx);
Yann Collet5b78d2f2015-11-12 15:36:05 +0100172 return dctx;
173}
174
175size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
176{
177 free(dctx);
Yann Collet982ffc72016-02-05 02:33:10 +0100178 return 0; /* reserved as a potential error code in the future */
Yann Collet5b78d2f2015-11-12 15:36:05 +0100179}
180
Yann Collet7b51a292016-01-26 15:58:49 +0100181void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
182{
183 memcpy(dstDCtx, srcDCtx,
184 sizeof(ZSTD_DCtx) - (BLOCKSIZE+WILDCOPY_OVERLENGTH + ZSTD_frameHeaderSize_max)); /* no need to copy workspace */
185}
186
Yann Collet5b78d2f2015-11-12 15:36:05 +0100187
Yann Collet03ea59b2016-03-12 01:25:40 +0100188/*-*************************************************************
Yann Collet5b78d2f2015-11-12 15:36:05 +0100189* Decompression section
190***************************************************************/
Yann Collet59d1f792016-01-23 19:28:41 +0100191
192/* Frame format description
193 Frame Header - [ Block Header - Block ] - Frame End
194 1) Frame Header
Yann Collet03ea59b2016-03-12 01:25:40 +0100195 - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_static.h)
196 - 1 byte - Frame Descriptor
Yann Collet59d1f792016-01-23 19:28:41 +0100197 2) Block Header
198 - 3 bytes, starting with a 2-bits descriptor
199 Uncompressed, Compressed, Frame End, unused
200 3) Block
201 See Block Format Description
202 4) Frame End
203 - 3 bytes, compatible with Block Header
204*/
205
Yann Collet03ea59b2016-03-12 01:25:40 +0100206
207/* Frame descriptor
208
209 1 byte, using :
210 bit 0-3 : windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN (see zstd_internal.h)
211 bit 4 : minmatch 4(0) or 3(1)
212 bit 5 : reserved (must be zero)
213 bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes
Yann Colletfb797352016-03-13 11:08:40 +0100214
215 Optional : content size (0, 1, 2 or 8 bytes)
216 0 : unknown
217 1 : 0-255 bytes
218 2 : 256 - 65535+256
219 8 : up to 16 exa
Yann Collet03ea59b2016-03-12 01:25:40 +0100220*/
221
222
223/* Compressed Block, format description
Yann Colletfb810d62016-01-28 00:18:06 +0100224
225 Block = Literal Section - Sequences Section
226 Prerequisite : size of (compressed) block, maximum size of regenerated data
227
Yann Collet59d1f792016-01-23 19:28:41 +0100228 1) Literal Section
Yann Colletfb810d62016-01-28 00:18:06 +0100229
230 1.1) Header : 1-5 bytes
231 flags: 2 bits
Yann Collet59d1f792016-01-23 19:28:41 +0100232 00 compressed by Huff0
Yann Colletfb810d62016-01-28 00:18:06 +0100233 01 unused
234 10 is Raw (uncompressed)
235 11 is Rle
236 Note : using 01 => Huff0 with precomputed table ?
Yann Collet59d1f792016-01-23 19:28:41 +0100237 Note : delta map ? => compressed ?
Yann Colletfb810d62016-01-28 00:18:06 +0100238
239 1.1.1) Huff0-compressed literal block : 3-5 bytes
240 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
241 srcSize < 1 KB => 3 bytes (2-2-10-10)
242 srcSize < 16KB => 4 bytes (2-2-14-14)
243 else => 5 bytes (2-2-18-18)
244 big endian convention
245
246 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
247 size : 5 bits: (IS_RAW<<6) + (0<<4) + size
248 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
249 size&255
250 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
251 size>>8&255
252 size&255
253
254 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
255 size : 5 bits: (IS_RLE<<6) + (0<<4) + size
256 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
257 size&255
258 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
259 size>>8&255
260 size&255
261
262 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
263 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
264 srcSize < 1 KB => 3 bytes (2-2-10-10)
265 srcSize < 16KB => 4 bytes (2-2-14-14)
266 else => 5 bytes (2-2-18-18)
267 big endian convention
268
269 1- CTable available (stored into workspace ?)
270 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
271
272
273 1.2) Literal block content
Yann Collet59d1f792016-01-23 19:28:41 +0100274
275 1.2.1) Huff0 block, using sizes from header
276 See Huff0 format
277
Yann Colletfb810d62016-01-28 00:18:06 +0100278 1.2.2) Huff0 block, using prepared table
Yann Collet59d1f792016-01-23 19:28:41 +0100279
Yann Colletfb810d62016-01-28 00:18:06 +0100280 1.2.3) Raw content
281
282 1.2.4) single byte
283
Yann Collet59d1f792016-01-23 19:28:41 +0100284
285 2) Sequences section
286 TO DO
287*/
288
Yann Collet03ea59b2016-03-12 01:25:40 +0100289static const size_t ZSTD_fcs_fieldSize[4] = { 0, 1, 2, 8 };
Yann Collet59d1f792016-01-23 19:28:41 +0100290
Yann Collet03ea59b2016-03-12 01:25:40 +0100291/** ZSTD_frameHeaderSize() :
292* srcSize must be >= ZSTD_frameHeaderSize_min.
293* @return : size of the Frame Header */
294static size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
Yann Collet88fcd292015-11-25 14:42:45 +0100295{
Yann Collet03ea59b2016-03-12 01:25:40 +0100296 U32 fcsId;
297 if (srcSize < ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);
298 fcsId = (((const BYTE*)src)[4]) >> 6;
299 return ZSTD_frameHeaderSize_min + ZSTD_fcs_fieldSize[fcsId];
Yann Collet88fcd292015-11-25 14:42:45 +0100300}
301
Yann Collet88fcd292015-11-25 14:42:45 +0100302
Yann Collet03ea59b2016-03-12 01:25:40 +0100303/** ZSTD_getFrameParams() :
304* decode Frame Header, or provide expected `srcSize`.
305* @return : 0, `fparamsPtr` is correctly filled,
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100306* >0, `srcSize` is too small, result is expected `srcSize`,
Yann Collet03ea59b2016-03-12 01:25:40 +0100307* or an error code, which can be tested using ZSTD_isError() */
Yann Collet09b21ee2016-03-15 12:56:03 +0100308size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize)
Yann Collet88fcd292015-11-25 14:42:45 +0100309{
Yann Collet03ea59b2016-03-12 01:25:40 +0100310 const BYTE* ip = (const BYTE*)src;
Yann Collet03ea59b2016-03-12 01:25:40 +0100311
312 if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_min;
Yann Colletd1b26842016-03-15 01:24:33 +0100313 if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
Yann Collet03ea59b2016-03-12 01:25:40 +0100314
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100315 /* ensure there is enough `srcSize` to fully read/decode frame header */
Yann Colletd1b26842016-03-15 01:24:33 +0100316 { size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize);
Yann Collet03ea59b2016-03-12 01:25:40 +0100317 if (srcSize < fhsize) return fhsize; }
318
Yann Collet0e491c02016-03-11 21:58:04 +0100319 memset(fparamsPtr, 0, sizeof(*fparamsPtr));
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100320 { BYTE const frameDesc = ip[4];
321 fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
322 fparamsPtr->mml = (frameDesc & 0x10) ? MINMATCH-1 : MINMATCH;
323 if ((frameDesc & 0x20) != 0) return ERROR(frameParameter_unsupported); /* reserved 1 bit */
324 switch(frameDesc >> 6) /* fcsId */
325 {
326 default: /* impossible */
327 case 0 : fparamsPtr->frameContentSize = 0; break;
328 case 1 : fparamsPtr->frameContentSize = ip[5]; break;
329 case 2 : fparamsPtr->frameContentSize = MEM_readLE16(ip+5)+256; break;
330 case 3 : fparamsPtr->frameContentSize = MEM_readLE64(ip+5); break;
331 } }
Yann Collet88fcd292015-11-25 14:42:45 +0100332 return 0;
333}
334
Yann Collet03ea59b2016-03-12 01:25:40 +0100335
336/** ZSTD_decodeFrameHeader() :
Yann Collet1c2c2bc2016-03-15 01:33:36 +0100337* `srcSize` must be the size provided by ZSTD_frameHeaderSize().
Yann Collet26415d32015-11-26 12:43:28 +0100338* @return : 0, or an error code, which can be tested using ZSTD_isError() */
Yann Collet03ea59b2016-03-12 01:25:40 +0100339static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* zc, const void* src, size_t srcSize)
Yann Collet26415d32015-11-26 12:43:28 +0100340{
Yann Collet03ea59b2016-03-12 01:25:40 +0100341 size_t result = ZSTD_getFrameParams(&(zc->fParams), src, srcSize);
Yann Collet0e491c02016-03-11 21:58:04 +0100342 if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
Yann Collet00fd7a22015-11-28 16:03:22 +0100343 return result;
Yann Collet26415d32015-11-26 12:43:28 +0100344}
345
Yann Collet5be2dd22015-11-11 13:43:58 +0100346
347size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
348{
349 const BYTE* const in = (const BYTE* const)src;
350 BYTE headerFlags;
351 U32 cSize;
352
Yann Collet61e16ce2016-01-31 02:04:15 +0100353 if (srcSize < 3)
354 return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100355
356 headerFlags = *in;
357 cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
358
359 bpPtr->blockType = (blockType_t)(headerFlags >> 6);
360 bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
361
362 if (bpPtr->blockType == bt_end) return 0;
363 if (bpPtr->blockType == bt_rle) return 1;
364 return cSize;
365}
366
Yann Collet59d1f792016-01-23 19:28:41 +0100367
Yann Collet0f366c62015-11-12 16:19:30 +0100368static size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100369{
370 if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
371 memcpy(dst, src, srcSize);
372 return srcSize;
373}
374
375
Yann Collet953ce722016-02-04 15:28:14 +0100376/*! ZSTD_decodeLiteralsBlock() :
Yann Collet14983e72015-11-11 21:38:21 +0100377 @return : nb of bytes read from src (< srcSize ) */
Yann Collet5b78d2f2015-11-12 15:36:05 +0100378size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
Yann Collet5be2dd22015-11-11 13:43:58 +0100379 const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
380{
Yann Collet5be2dd22015-11-11 13:43:58 +0100381 const BYTE* const istart = (const BYTE*) src;
382
383 /* any compressed block with literals segment must be at least this size */
384 if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
385
Yann Collet59d1f792016-01-23 19:28:41 +0100386 switch(istart[0]>> 6)
Yann Collet5be2dd22015-11-11 13:43:58 +0100387 {
Yann Collet59d1f792016-01-23 19:28:41 +0100388 case IS_HUF:
Yann Collet5be2dd22015-11-11 13:43:58 +0100389 {
Yann Colletafe07092016-01-25 04:10:46 +0100390 size_t litSize, litCSize, singleStream=0;
Yann Collet59d1f792016-01-23 19:28:41 +0100391 U32 lhSize = ((istart[0]) >> 4) & 3;
392 switch(lhSize)
393 {
394 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
395 /* 2 - 2 - 10 - 10 */
396 lhSize=3;
Yann Colletafe07092016-01-25 04:10:46 +0100397 singleStream = istart[0] & 16;
Yann Collet59d1f792016-01-23 19:28:41 +0100398 litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
399 litCSize = ((istart[1] & 3) << 8) + istart[2];
400 break;
401 case 2:
402 /* 2 - 2 - 14 - 14 */
403 lhSize=4;
404 litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);
405 litCSize = ((istart[2] & 63) << 8) + istart[3];
406 break;
407 case 3:
408 /* 2 - 2 - 18 - 18 */
409 lhSize=5;
410 litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);
411 litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];
412 break;
413 }
Yann Colletfb810d62016-01-28 00:18:06 +0100414 if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100415
Yann Colletafe07092016-01-25 04:10:46 +0100416 if (HUF_isError(singleStream ?
417 HUF_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :
418 HUF_decompress (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))
Yann Collet59d1f792016-01-23 19:28:41 +0100419 return ERROR(corruption_detected);
420
Yann Collet5be2dd22015-11-11 13:43:58 +0100421 dctx->litPtr = dctx->litBuffer;
422 dctx->litBufSize = BLOCKSIZE+8;
423 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100424 return litCSize + lhSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100425 }
Yann Colletb923f652016-01-26 03:14:20 +0100426 case IS_PCH:
427 {
428 size_t errorCode;
429 size_t litSize, litCSize;
430 U32 lhSize = ((istart[0]) >> 4) & 3;
431 if (lhSize != 1) /* only case supported for now : small litSize, single stream */
432 return ERROR(corruption_detected);
Yann Colletfb810d62016-01-28 00:18:06 +0100433 if (!dctx->flagStaticTables)
Yann Collet7b51a292016-01-26 15:58:49 +0100434 return ERROR(dictionary_corrupted);
Yann Colletb923f652016-01-26 03:14:20 +0100435
436 /* 2 - 2 - 10 - 10 */
437 lhSize=3;
438 litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
439 litCSize = ((istart[1] & 3) << 8) + istart[2];
440
441 errorCode = HUF_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
442 if (HUF_isError(errorCode)) return ERROR(corruption_detected);
443
444 dctx->litPtr = dctx->litBuffer;
445 dctx->litBufSize = BLOCKSIZE+WILDCOPY_OVERLENGTH;
446 dctx->litSize = litSize;
447 return litCSize + lhSize;
448 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100449 case IS_RAW:
450 {
Yann Collet59d1f792016-01-23 19:28:41 +0100451 size_t litSize;
452 U32 lhSize = ((istart[0]) >> 4) & 3;
453 switch(lhSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100454 {
Yann Collet59d1f792016-01-23 19:28:41 +0100455 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
456 lhSize=1;
457 litSize = istart[0] & 31;
458 break;
459 case 2:
460 litSize = ((istart[0] & 15) << 8) + istart[1];
461 break;
462 case 3:
463 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
464 break;
465 }
466
Yann Collet61e16ce2016-01-31 02:04:15 +0100467 if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
Yann Colletb010b3b2016-02-03 12:39:34 +0100468 if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100469 memcpy(dctx->litBuffer, istart+lhSize, litSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100470 dctx->litPtr = dctx->litBuffer;
471 dctx->litBufSize = BLOCKSIZE+8;
472 dctx->litSize = litSize;
Yann Colletbc4c8aa2016-01-25 17:26:01 +0100473 return lhSize+litSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100474 }
475 /* direct reference into compressed stream */
Yann Collet59d1f792016-01-23 19:28:41 +0100476 dctx->litPtr = istart+lhSize;
477 dctx->litBufSize = srcSize-lhSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100478 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100479 return lhSize+litSize;
480 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100481 case IS_RLE:
482 {
Yann Collet59d1f792016-01-23 19:28:41 +0100483 size_t litSize;
484 U32 lhSize = ((istart[0]) >> 4) & 3;
485 switch(lhSize)
486 {
487 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
488 lhSize = 1;
489 litSize = istart[0] & 31;
490 break;
491 case 2:
492 litSize = ((istart[0] & 15) << 8) + istart[1];
493 break;
494 case 3:
495 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
496 break;
497 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100498 if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100499 memset(dctx->litBuffer, istart[lhSize], litSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100500 dctx->litPtr = dctx->litBuffer;
Yann Colletb923f652016-01-26 03:14:20 +0100501 dctx->litBufSize = BLOCKSIZE+WILDCOPY_OVERLENGTH;
Yann Collet5be2dd22015-11-11 13:43:58 +0100502 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100503 return lhSize+1;
Yann Collet5be2dd22015-11-11 13:43:58 +0100504 }
Yann Colletb923f652016-01-26 03:14:20 +0100505 default:
506 return ERROR(corruption_detected); /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100507 }
508}
509
510
511size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
512 FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
513 const void* src, size_t srcSize)
514{
515 const BYTE* const istart = (const BYTE* const)src;
516 const BYTE* ip = istart;
517 const BYTE* const iend = istart + srcSize;
518 U32 LLtype, Offtype, MLtype;
519 U32 LLlog, Offlog, MLlog;
520 size_t dumpsLength;
521
522 /* check */
Yann Collet61e16ce2016-01-31 02:04:15 +0100523 if (srcSize < MIN_SEQUENCES_SIZE)
524 return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100525
526 /* SeqHead */
Yann Collet61e16ce2016-01-31 02:04:15 +0100527 *nbSeq = *ip++;
528 if (*nbSeq==0) return 1;
Yann Colletd409db62016-03-04 14:45:31 +0100529 if (*nbSeq >= 0x7F) {
530 if (*nbSeq == 0xFF)
531 *nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
532 else
533 *nbSeq = ((nbSeq[0]-0x80)<<8) + *ip++;
534 }
Yann Collete93d6ce2016-01-31 00:58:06 +0100535
Yann Colletd409db62016-03-04 14:45:31 +0100536 /* FSE table descriptors */
Yann Collet5be2dd22015-11-11 13:43:58 +0100537 LLtype = *ip >> 6;
538 Offtype = (*ip >> 4) & 3;
539 MLtype = (*ip >> 2) & 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100540 if (*ip & 2) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100541 dumpsLength = ip[2];
542 dumpsLength += ip[1] << 8;
543 ip += 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100544 } else {
Yann Collet5be2dd22015-11-11 13:43:58 +0100545 dumpsLength = ip[1];
546 dumpsLength += (ip[0] & 1) << 8;
547 ip += 2;
548 }
549 *dumpsPtr = ip;
550 ip += dumpsLength;
551 *dumpsLengthPtr = dumpsLength;
552
553 /* check */
554 if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
555
556 /* sequences */
557 {
Yann Collet82368cf2015-11-16 19:10:56 +0100558 S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL >= MaxOff */
Yann Collet5be2dd22015-11-11 13:43:58 +0100559 size_t headerSize;
560
561 /* Build DTables */
562 switch(LLtype)
563 {
564 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100565 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100566 LLlog = 0;
Yann Colletfb810d62016-01-28 00:18:06 +0100567 FSE_buildDTable_rle(DTableLL, *ip++);
568 break;
569 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100570 LLlog = LLbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100571 FSE_buildDTable_raw(DTableLL, LLbits);
572 break;
573 case FSE_ENCODING_STATIC:
574 break;
575 case FSE_ENCODING_DYNAMIC :
576 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100577 max = MaxLL;
578 headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
579 if (FSE_isError(headerSize)) return ERROR(GENERIC);
580 if (LLlog > LLFSELog) return ERROR(corruption_detected);
581 ip += headerSize;
582 FSE_buildDTable(DTableLL, norm, max, LLlog);
583 }
584
585 switch(Offtype)
586 {
587 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100588 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100589 Offlog = 0;
590 if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
591 FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */
592 break;
Yann Colletfb810d62016-01-28 00:18:06 +0100593 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100594 Offlog = Offbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100595 FSE_buildDTable_raw(DTableOffb, Offbits);
596 break;
597 case FSE_ENCODING_STATIC:
598 break;
599 case FSE_ENCODING_DYNAMIC :
600 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100601 max = MaxOff;
602 headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
603 if (FSE_isError(headerSize)) return ERROR(GENERIC);
604 if (Offlog > OffFSELog) return ERROR(corruption_detected);
605 ip += headerSize;
606 FSE_buildDTable(DTableOffb, norm, max, Offlog);
607 }
608
609 switch(MLtype)
610 {
611 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100612 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100613 MLlog = 0;
614 if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
Yann Colletfb810d62016-01-28 00:18:06 +0100615 FSE_buildDTable_rle(DTableML, *ip++);
616 break;
617 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100618 MLlog = MLbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100619 FSE_buildDTable_raw(DTableML, MLbits);
620 break;
621 case FSE_ENCODING_STATIC:
622 break;
623 case FSE_ENCODING_DYNAMIC :
624 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100625 max = MaxML;
626 headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
627 if (FSE_isError(headerSize)) return ERROR(GENERIC);
628 if (MLlog > MLFSELog) return ERROR(corruption_detected);
629 ip += headerSize;
630 FSE_buildDTable(DTableML, norm, max, MLlog);
Yann Colletfb810d62016-01-28 00:18:06 +0100631 } }
Yann Collet5be2dd22015-11-11 13:43:58 +0100632
633 return ip-istart;
634}
635
636
637typedef struct {
638 size_t litLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100639 size_t matchLength;
Yann Collete93d6ce2016-01-31 00:58:06 +0100640 size_t offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100641} seq_t;
642
643typedef struct {
644 BIT_DStream_t DStream;
645 FSE_DState_t stateLL;
646 FSE_DState_t stateOffb;
647 FSE_DState_t stateML;
648 size_t prevOffset;
649 const BYTE* dumps;
650 const BYTE* dumpsEnd;
651} seqState_t;
652
inikepe9f30ea2016-02-03 12:53:07 +0100653
654
inikep6b3739c2016-02-22 15:53:42 +0100655static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
Yann Collet5be2dd22015-11-11 13:43:58 +0100656{
657 size_t litLength;
658 size_t prevOffset;
659 size_t offset;
660 size_t matchLength;
661 const BYTE* dumps = seqState->dumps;
662 const BYTE* const de = seqState->dumpsEnd;
663
664 /* Literal length */
Yann Collete93d6ce2016-01-31 00:58:06 +0100665 litLength = FSE_peakSymbol(&(seqState->stateLL));
Yann Collete4fdad52015-11-25 21:09:17 +0100666 prevOffset = litLength ? seq->offset : seqState->prevOffset;
Yann Colletfb810d62016-01-28 00:18:06 +0100667 if (litLength == MaxLL) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100668 U32 add = *dumps++;
669 if (add < 255) litLength += add;
Yann Colletfb810d62016-01-28 00:18:06 +0100670 else {
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100671 litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no risk : dumps is always followed by seq tables > 1 byte */
672 if (litLength&1) litLength>>=1, dumps += 3;
673 else litLength = (U16)(litLength)>>1, dumps += 2;
Yann Collet5be2dd22015-11-11 13:43:58 +0100674 }
675 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
676 }
677
678 /* Offset */
679 {
680 static const U32 offsetPrefix[MaxOff+1] = {
Yann Collet95cd0c22016-03-08 18:24:21 +0100681 1 /*fake*/, 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100,
682 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000,
683 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, /*fake*/ 1, 1, 1, 1 };
Yann Collete93d6ce2016-01-31 00:58:06 +0100684 U32 offsetCode = FSE_peakSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
685 U32 nbBits = offsetCode - 1;
Yann Collet5be2dd22015-11-11 13:43:58 +0100686 if (offsetCode==0) nbBits = 0; /* cmove */
687 offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);
688 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
Yann Collete93d6ce2016-01-31 00:58:06 +0100689 if (offsetCode==0) offset = prevOffset; /* repcode, cmove */
Yann Collet55aa7f92015-11-20 12:04:52 +0100690 if (offsetCode | !litLength) seqState->prevOffset = seq->offset; /* cmove */
Yann Collete93d6ce2016-01-31 00:58:06 +0100691 FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* update */
Yann Collet5be2dd22015-11-11 13:43:58 +0100692 }
693
Yann Collete93d6ce2016-01-31 00:58:06 +0100694 /* Literal length update */
695 FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); /* update */
696 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
697
Yann Collet5be2dd22015-11-11 13:43:58 +0100698 /* MatchLength */
699 matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
Yann Colletfb810d62016-01-28 00:18:06 +0100700 if (matchLength == MaxML) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100701 U32 add = *dumps++;
702 if (add < 255) matchLength += add;
Yann Colletfb810d62016-01-28 00:18:06 +0100703 else {
Yann Collet5be2dd22015-11-11 13:43:58 +0100704 matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100705 if (matchLength&1) matchLength>>=1, dumps += 3;
706 else matchLength = (U16)(matchLength)>>1, dumps += 2;
Yann Collet5be2dd22015-11-11 13:43:58 +0100707 }
708 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
709 }
inikep6b3739c2016-02-22 15:53:42 +0100710 matchLength += mls;
Yann Collet5be2dd22015-11-11 13:43:58 +0100711
712 /* save result */
713 seq->litLength = litLength;
714 seq->offset = offset;
715 seq->matchLength = matchLength;
716 seqState->dumps = dumps;
Yann Colletfb810d62016-01-28 00:18:06 +0100717
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100718#if 0 /* debug */
Yann Colletfb810d62016-01-28 00:18:06 +0100719 {
720 static U64 totalDecoded = 0;
721 printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
722 (U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);
723 totalDecoded += litLength + matchLength;
724 }
725#endif
Yann Collet5be2dd22015-11-11 13:43:58 +0100726}
727
728
Yann Collet5b78d2f2015-11-12 15:36:05 +0100729FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
Yann Colletb3a2af92015-11-19 17:13:19 +0100730 BYTE* const oend, seq_t sequence,
Yann Collet5be2dd22015-11-11 13:43:58 +0100731 const BYTE** litPtr, const BYTE* const litLimit_8,
Yann Collet417890c2015-12-04 17:16:37 +0100732 const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
Yann Collet5be2dd22015-11-11 13:43:58 +0100733{
Yann Colletb3a2af92015-11-19 17:13:19 +0100734 static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
735 static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
Yann Collet5be2dd22015-11-11 13:43:58 +0100736 BYTE* const oLitEnd = op + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100737 const size_t sequenceLength = sequence.litLength + sequence.matchLength;
738 BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
Yann Collet5be2dd22015-11-11 13:43:58 +0100739 BYTE* const oend_8 = oend-8;
740 const BYTE* const litEnd = *litPtr + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100741 const BYTE* match = oLitEnd - sequence.offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100742
743 /* check */
744 if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
745 if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
746 if (litEnd > litLimit_8) return ERROR(corruption_detected); /* risk read beyond lit buffer */
747
748 /* copy Literals */
749 ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
750 op = oLitEnd;
751 *litPtr = litEnd; /* update for next sequence */
752
753 /* copy Match */
Yann Collet7b51a292016-01-26 15:58:49 +0100754 if (sequence.offset > (size_t)(oLitEnd - base)) {
Yann Collet44287a32015-11-30 23:13:56 +0100755 /* offset beyond prefix */
Yann Collet9f5ab1a2015-12-11 00:27:41 +0100756 if (sequence.offset > (size_t)(oLitEnd - vBase))
757 return ERROR(corruption_detected);
Yann Collet44287a32015-11-30 23:13:56 +0100758 match = dictEnd - (base-match);
Yann Collet7b51a292016-01-26 15:58:49 +0100759 if (match + sequence.matchLength <= dictEnd) {
Yann Collet4bfe4152015-12-06 13:18:37 +0100760 memmove(oLitEnd, match, sequence.matchLength);
Yann Collet44287a32015-11-30 23:13:56 +0100761 return sequenceLength;
762 }
763 /* span extDict & currentPrefixSegment */
764 {
765 size_t length1 = dictEnd - match;
Yann Collet4bfe4152015-12-06 13:18:37 +0100766 memmove(oLitEnd, match, length1);
Yann Collet44287a32015-11-30 23:13:56 +0100767 op = oLitEnd + length1;
768 sequence.matchLength -= length1;
769 match = base;
Yann Colletfb810d62016-01-28 00:18:06 +0100770 } }
Yann Collet0f366c62015-11-12 16:19:30 +0100771
Yann Collet44287a32015-11-30 23:13:56 +0100772 /* match within prefix */
Yann Collet7b51a292016-01-26 15:58:49 +0100773 if (sequence.offset < 8) {
Yann Collet44287a32015-11-30 23:13:56 +0100774 /* close range match, overlap */
775 const int sub2 = dec64table[sequence.offset];
776 op[0] = match[0];
777 op[1] = match[1];
778 op[2] = match[2];
779 op[3] = match[3];
780 match += dec32table[sequence.offset];
781 ZSTD_copy4(op+4, match);
782 match -= sub2;
Yann Colletfb810d62016-01-28 00:18:06 +0100783 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100784 ZSTD_copy8(op, match);
785 }
786 op += 8; match += 8;
Yann Collet5be2dd22015-11-11 13:43:58 +0100787
inikepa4dde252016-03-01 14:14:35 +0100788 if (oMatchEnd > oend-(16-3)) { // 3 = MINMATCH
Yann Collet7b51a292016-01-26 15:58:49 +0100789 if (op < oend_8) {
Yann Collet44287a32015-11-30 23:13:56 +0100790 ZSTD_wildcopy(op, match, oend_8 - op);
791 match += oend_8 - op;
792 op = oend_8;
793 }
Yann Colletfb810d62016-01-28 00:18:06 +0100794 while (op < oMatchEnd)
795 *op++ = *match++;
796 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100797 ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
798 }
799 return sequenceLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100800}
801
Yann Colletb3a2af92015-11-19 17:13:19 +0100802
Yann Collet5be2dd22015-11-11 13:43:58 +0100803static size_t ZSTD_decompressSequences(
Yann Collet5b78d2f2015-11-12 15:36:05 +0100804 ZSTD_DCtx* dctx,
Yann Collet5be2dd22015-11-11 13:43:58 +0100805 void* dst, size_t maxDstSize,
806 const void* seqStart, size_t seqSize)
807{
Yann Collet5be2dd22015-11-11 13:43:58 +0100808 const BYTE* ip = (const BYTE*)seqStart;
809 const BYTE* const iend = ip + seqSize;
810 BYTE* const ostart = (BYTE* const)dst;
811 BYTE* op = ostart;
812 BYTE* const oend = ostart + maxDstSize;
813 size_t errorCode, dumpsLength;
814 const BYTE* litPtr = dctx->litPtr;
815 const BYTE* const litLimit_8 = litPtr + dctx->litBufSize - 8;
816 const BYTE* const litEnd = litPtr + dctx->litSize;
817 int nbSeq;
818 const BYTE* dumps;
819 U32* DTableLL = dctx->LLTable;
820 U32* DTableML = dctx->MLTable;
821 U32* DTableOffb = dctx->OffTable;
Yann Collet417890c2015-12-04 17:16:37 +0100822 const BYTE* const base = (const BYTE*) (dctx->base);
823 const BYTE* const vBase = (const BYTE*) (dctx->vBase);
824 const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
Yann Collet0e491c02016-03-11 21:58:04 +0100825 const U32 mls = dctx->fParams.mml;
Yann Collet5be2dd22015-11-11 13:43:58 +0100826
827 /* Build Decoding Tables */
828 errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
829 DTableLL, DTableML, DTableOffb,
Yann Colletfb810d62016-01-28 00:18:06 +0100830 ip, seqSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100831 if (ZSTD_isError(errorCode)) return errorCode;
832 ip += errorCode;
833
834 /* Regen sequences */
Yann Collete93d6ce2016-01-31 00:58:06 +0100835 if (nbSeq) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100836 seq_t sequence;
837 seqState_t seqState;
838
839 memset(&sequence, 0, sizeof(sequence));
Yann Collet61e16ce2016-01-31 02:04:15 +0100840 sequence.offset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100841 seqState.dumps = dumps;
842 seqState.dumpsEnd = dumps + dumpsLength;
Yann Collet61e16ce2016-01-31 02:04:15 +0100843 seqState.prevOffset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100844 errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
845 if (ERR_isError(errorCode)) return ERROR(corruption_detected);
846 FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
847 FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
848 FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
849
Yann Collet7b51a292016-01-26 15:58:49 +0100850 for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
Yann Colletb3a2af92015-11-19 17:13:19 +0100851 size_t oneSeqSize;
852 nbSeq--;
inikep6b3739c2016-02-22 15:53:42 +0100853 ZSTD_decodeSequence(&sequence, &seqState, mls);
Yann Colletb3a2af92015-11-19 17:13:19 +0100854 oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_8, base, vBase, dictEnd);
Yann Collet370b08e2016-03-08 00:03:59 +0100855 if (ZSTD_isError(oneSeqSize))
856 return oneSeqSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100857 op += oneSeqSize;
858 }
859
860 /* check if reached exact end */
Yann Collet35f7de52016-01-31 02:51:03 +0100861 if (nbSeq) return ERROR(corruption_detected);
Yann Collete93d6ce2016-01-31 00:58:06 +0100862 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100863
Yann Collete93d6ce2016-01-31 00:58:06 +0100864 /* last literal segment */
865 {
866 size_t lastLLSize = litEnd - litPtr;
867 if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */
868 if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
869 memcpy(op, litPtr, lastLLSize);
870 op += lastLLSize;
871 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100872
873 return op-ostart;
874}
875
876
Yann Colletb0125102016-01-09 02:00:10 +0100877static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
878{
Yann Collet7b51a292016-01-26 15:58:49 +0100879 if (dst != dctx->previousDstEnd) { /* not contiguous */
Yann Colletb0125102016-01-09 02:00:10 +0100880 dctx->dictEnd = dctx->previousDstEnd;
881 dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
882 dctx->base = dst;
883 dctx->previousDstEnd = dst;
884 }
885}
886
887
888static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100889 void* dst, size_t dstCapacity,
Yann Collet5be2dd22015-11-11 13:43:58 +0100890 const void* src, size_t srcSize)
Yann Colletb010b3b2016-02-03 12:39:34 +0100891{ /* blockType == blockCompressed */
Yann Collet5be2dd22015-11-11 13:43:58 +0100892 const BYTE* ip = (const BYTE*)src;
Yann Colletb010b3b2016-02-03 12:39:34 +0100893 size_t litCSize;
894
895 if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100896
inikepa4dde252016-03-01 14:14:35 +0100897 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBlock_internal searchLength=%d\n", dctx->base, dctx->params.searchLength);
898
Yann Collet5be2dd22015-11-11 13:43:58 +0100899 /* Decode literals sub-block */
Yann Colletb010b3b2016-02-03 12:39:34 +0100900 litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100901 if (ZSTD_isError(litCSize)) return litCSize;
902 ip += litCSize;
903 srcSize -= litCSize;
904
Yann Colletb010b3b2016-02-03 12:39:34 +0100905 return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100906}
907
908
Yann Colletb0125102016-01-09 02:00:10 +0100909size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100910 void* dst, size_t dstCapacity,
Yann Colletb0125102016-01-09 02:00:10 +0100911 const void* src, size_t srcSize)
912{
913 ZSTD_checkContinuity(dctx, dst);
Yann Colletb010b3b2016-02-03 12:39:34 +0100914 return ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
Yann Colletb0125102016-01-09 02:00:10 +0100915}
916
917
Yann Collet0e491c02016-03-11 21:58:04 +0100918/*! ZSTD_decompress_continueDCtx() :
919* `dctx` must have been properly initialized */
920static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
Yann Collet31683c02015-12-18 01:26:48 +0100921 void* dst, size_t maxDstSize,
Yann Collet7b51a292016-01-26 15:58:49 +0100922 const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100923{
924 const BYTE* ip = (const BYTE*)src;
925 const BYTE* iend = ip + srcSize;
926 BYTE* const ostart = (BYTE* const)dst;
927 BYTE* op = ostart;
928 BYTE* const oend = ostart + maxDstSize;
929 size_t remainingSize = srcSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100930 blockProperties_t blockProperties;
931
932 /* Frame Header */
Yann Collet88fcd292015-11-25 14:42:45 +0100933 {
Yann Collet03ea59b2016-03-12 01:25:40 +0100934 size_t frameHeaderSize, errorCode;
Yann Collet88fcd292015-11-25 14:42:45 +0100935 if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100936#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
Yann Collet88fcd292015-11-25 14:42:45 +0100937 {
938 const U32 magicNumber = MEM_readLE32(src);
939 if (ZSTD_isLegacy(magicNumber))
940 return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber);
941 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100942#endif
Yann Collet03ea59b2016-03-12 01:25:40 +0100943 frameHeaderSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
Yann Collet88fcd292015-11-25 14:42:45 +0100944 if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
945 if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
Yann Collet03ea59b2016-03-12 01:25:40 +0100946 errorCode = ZSTD_decodeFrameHeader(dctx, src, frameHeaderSize);
947 if (ZSTD_isError(errorCode)) return errorCode;
Yann Collet88fcd292015-11-25 14:42:45 +0100948 ip += frameHeaderSize; remainingSize -= frameHeaderSize;
Yann Collet88fcd292015-11-25 14:42:45 +0100949 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100950
951 /* Loop on each block */
952 while (1)
953 {
954 size_t decodedSize=0;
955 size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
956 if (ZSTD_isError(cBlockSize)) return cBlockSize;
957
958 ip += ZSTD_blockHeaderSize;
959 remainingSize -= ZSTD_blockHeaderSize;
960 if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
961
962 switch(blockProperties.blockType)
963 {
964 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +0100965 decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100966 break;
967 case bt_raw :
Yann Collet0f366c62015-11-12 16:19:30 +0100968 decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100969 break;
970 case bt_rle :
971 return ERROR(GENERIC); /* not yet supported */
972 break;
973 case bt_end :
974 /* end of frame */
975 if (remainingSize) return ERROR(srcSize_wrong);
976 break;
977 default:
978 return ERROR(GENERIC); /* impossible */
979 }
980 if (cBlockSize == 0) break; /* bt_end */
981
982 if (ZSTD_isError(decodedSize)) return decodedSize;
983 op += decodedSize;
984 ip += cBlockSize;
985 remainingSize -= cBlockSize;
986 }
987
988 return op-ostart;
989}
990
Yann Collet31683c02015-12-18 01:26:48 +0100991
Yann Collet7b51a292016-01-26 15:58:49 +0100992size_t ZSTD_decompress_usingPreparedDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* refDCtx,
993 void* dst, size_t maxDstSize,
994 const void* src, size_t srcSize)
995{
996 ZSTD_copyDCtx(dctx, refDCtx);
997 ZSTD_checkContinuity(dctx, dst);
Yann Collet0e491c02016-03-11 21:58:04 +0100998 return ZSTD_decompressFrame(dctx, dst, maxDstSize, src, srcSize);
Yann Collet7b51a292016-01-26 15:58:49 +0100999}
1000
1001
1002size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
1003 void* dst, size_t maxDstSize,
1004 const void* src, size_t srcSize,
1005 const void* dict, size_t dictSize)
1006{
1007 ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
inikepa4dde252016-03-01 14:14:35 +01001008 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin_usingDict searchLength=%d\n", dctx->base, dctx->params.searchLength);
Yann Collet7b51a292016-01-26 15:58:49 +01001009 ZSTD_checkContinuity(dctx, dst);
Yann Collet0e491c02016-03-11 21:58:04 +01001010 return ZSTD_decompressFrame(dctx, dst, maxDstSize, src, srcSize);
Yann Collet7b51a292016-01-26 15:58:49 +01001011}
1012
1013
Yann Collet31683c02015-12-18 01:26:48 +01001014size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
1015{
1016 return ZSTD_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);
1017}
1018
Yann Collet0e491c02016-03-11 21:58:04 +01001019
Yann Collet5be2dd22015-11-11 13:43:58 +01001020size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
1021{
Yann Collet3a3b72f2016-01-11 12:56:11 +01001022#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
1023 size_t regenSize;
1024 ZSTD_DCtx* dctx = ZSTD_createDCtx();
1025 if (dctx==NULL) return ERROR(memory_allocation);
1026 regenSize = ZSTD_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);
1027 ZSTD_freeDCtx(dctx);
1028 return regenSize;
1029#else
Yann Collet31683c02015-12-18 01:26:48 +01001030 ZSTD_DCtx dctx;
1031 return ZSTD_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);
Yann Colleta768a302016-01-21 16:04:35 +01001032#endif
Yann Collet5be2dd22015-11-11 13:43:58 +01001033}
1034
1035
1036/* ******************************
1037* Streaming Decompression API
1038********************************/
Yann Collet5be2dd22015-11-11 13:43:58 +01001039size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)
1040{
1041 return dctx->expected;
1042}
1043
Yann Collet37422192016-01-25 16:54:05 +01001044size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +01001045{
1046 /* Sanity check */
Yann Collet37422192016-01-25 16:54:05 +01001047 if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
1048 ZSTD_checkContinuity(dctx, dst);
Yann Collet5be2dd22015-11-11 13:43:58 +01001049
Yann Collet88fcd292015-11-25 14:42:45 +01001050 /* Decompress : frame header; part 1 */
Yann Collet37422192016-01-25 16:54:05 +01001051 switch (dctx->stage)
Yann Collet5be2dd22015-11-11 13:43:58 +01001052 {
Yann Collet88fcd292015-11-25 14:42:45 +01001053 case ZSTDds_getFrameHeaderSize :
Yann Collet5be2dd22015-11-11 13:43:58 +01001054 {
Yann Collet88fcd292015-11-25 14:42:45 +01001055 /* get frame header size */
1056 if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
Yann Collet03ea59b2016-03-12 01:25:40 +01001057 dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_min);
Yann Collet37422192016-01-25 16:54:05 +01001058 if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
1059 memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
Yann Collet7b51a292016-01-26 15:58:49 +01001060 if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
Yann Collet37422192016-01-25 16:54:05 +01001061 dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_min;
1062 dctx->stage = ZSTDds_decodeFrameHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001063 return 0;
1064 }
Yann Collet37422192016-01-25 16:54:05 +01001065 dctx->expected = 0; /* not necessary to copy more */
Yann Collet5be2dd22015-11-11 13:43:58 +01001066 }
Yann Collet88fcd292015-11-25 14:42:45 +01001067 case ZSTDds_decodeFrameHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001068 {
Yann Collet88fcd292015-11-25 14:42:45 +01001069 /* get frame header */
1070 size_t result;
Yann Collet37422192016-01-25 16:54:05 +01001071 memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
Yann Collet03ea59b2016-03-12 01:25:40 +01001072 result = ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001073 if (ZSTD_isError(result)) return result;
Yann Collet37422192016-01-25 16:54:05 +01001074 dctx->expected = ZSTD_blockHeaderSize;
1075 dctx->stage = ZSTDds_decodeBlockHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001076 return 0;
Yann Collet5be2dd22015-11-11 13:43:58 +01001077 }
Yann Collet88fcd292015-11-25 14:42:45 +01001078 case ZSTDds_decodeBlockHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001079 {
Yann Collet88fcd292015-11-25 14:42:45 +01001080 /* Decode block header */
1081 blockProperties_t bp;
1082 size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
1083 if (ZSTD_isError(blockSize)) return blockSize;
Yann Collet7b51a292016-01-26 15:58:49 +01001084 if (bp.blockType == bt_end) {
Yann Collet37422192016-01-25 16:54:05 +01001085 dctx->expected = 0;
1086 dctx->stage = ZSTDds_getFrameHeaderSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001087 }
Yann Collet7b51a292016-01-26 15:58:49 +01001088 else {
Yann Collet37422192016-01-25 16:54:05 +01001089 dctx->expected = blockSize;
1090 dctx->bType = bp.blockType;
1091 dctx->stage = ZSTDds_decompressBlock;
Yann Collet88fcd292015-11-25 14:42:45 +01001092 }
Yann Collet88fcd292015-11-25 14:42:45 +01001093 return 0;
1094 }
Yann Collet417890c2015-12-04 17:16:37 +01001095 case ZSTDds_decompressBlock:
Yann Collet88fcd292015-11-25 14:42:45 +01001096 {
1097 /* Decompress : block content */
1098 size_t rSize;
Yann Collet37422192016-01-25 16:54:05 +01001099 switch(dctx->bType)
Yann Collet88fcd292015-11-25 14:42:45 +01001100 {
1101 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +01001102 rSize = ZSTD_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001103 break;
1104 case bt_raw :
1105 rSize = ZSTD_copyRawBlock(dst, maxDstSize, src, srcSize);
1106 break;
1107 case bt_rle :
1108 return ERROR(GENERIC); /* not yet handled */
1109 break;
1110 case bt_end : /* should never happen (filtered at phase 1) */
1111 rSize = 0;
1112 break;
1113 default:
Yann Collet7b51a292016-01-26 15:58:49 +01001114 return ERROR(GENERIC); /* impossible */
Yann Collet88fcd292015-11-25 14:42:45 +01001115 }
Yann Collet37422192016-01-25 16:54:05 +01001116 dctx->stage = ZSTDds_decodeBlockHeader;
1117 dctx->expected = ZSTD_blockHeaderSize;
1118 dctx->previousDstEnd = (char*)dst + rSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001119 return rSize;
1120 }
1121 default:
1122 return ERROR(GENERIC); /* impossible */
1123 }
Yann Collet5be2dd22015-11-11 13:43:58 +01001124}
1125
1126
Yann Colletb923f652016-01-26 03:14:20 +01001127static void ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Collet417890c2015-12-04 17:16:37 +01001128{
Yann Collet37422192016-01-25 16:54:05 +01001129 dctx->dictEnd = dctx->previousDstEnd;
1130 dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
1131 dctx->base = dict;
1132 dctx->previousDstEnd = (const char*)dict + dictSize;
Yann Collet417890c2015-12-04 17:16:37 +01001133}
Yann Colletb923f652016-01-26 03:14:20 +01001134
Yann Colletb923f652016-01-26 03:14:20 +01001135static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1136{
Yann Colletfb810d62016-01-28 00:18:06 +01001137 size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;
1138 short offcodeNCount[MaxOff+1];
1139 U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
1140 short matchlengthNCount[MaxML+1];
1141 unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
1142 short litlengthNCount[MaxLL+1];
1143 unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
1144
1145 hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize);
Yann Colletb923f652016-01-26 03:14:20 +01001146 if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
Yann Colletfb810d62016-01-28 00:18:06 +01001147 dict = (const char*)dict + hSize;
1148 dictSize -= hSize;
1149
1150 offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
1151 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
1152 errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
1153 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1154 dict = (const char*)dict + offcodeHeaderSize;
1155 dictSize -= offcodeHeaderSize;
1156
1157 matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
1158 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
1159 errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
1160 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1161 dict = (const char*)dict + matchlengthHeaderSize;
1162 dictSize -= matchlengthHeaderSize;
1163
1164 litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
1165 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
1166 errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
1167 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1168
1169 dctx->flagStaticTables = 1;
1170 return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
Yann Colletb923f652016-01-26 03:14:20 +01001171}
1172
Yann Collet7b51a292016-01-26 15:58:49 +01001173static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Colletb923f652016-01-26 03:14:20 +01001174{
1175 size_t eSize;
1176 U32 magic = MEM_readLE32(dict);
1177 if (magic != ZSTD_DICT_MAGIC) {
1178 /* pure content mode */
1179 ZSTD_refDictContent(dctx, dict, dictSize);
1180 return 0;
1181 }
1182 /* load entropy tables */
1183 dict = (const char*)dict + 4;
1184 dictSize -= 4;
1185 eSize = ZSTD_loadEntropy(dctx, dict, dictSize);
1186 if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
1187
1188 /* reference dictionary content */
1189 dict = (const char*)dict + eSize;
1190 dictSize -= eSize;
1191 ZSTD_refDictContent(dctx, dict, dictSize);
1192
1193 return 0;
1194}
1195
Yann Collet7b51a292016-01-26 15:58:49 +01001196
1197size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1198{
1199 size_t errorCode;
1200 errorCode = ZSTD_decompressBegin(dctx);
1201 if (ZSTD_isError(errorCode)) return errorCode;
1202
1203 if (dict && dictSize) {
1204 errorCode = ZSTD_decompress_insertDictionary(dctx, dict, dictSize);
1205 if (ZSTD_isError(errorCode)) return ERROR(dictionary_corrupted);
1206 }
1207
1208 return 0;
1209}
1210