blob: c4338bcc2187b7600af1d7739961e137d4e4d239 [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
97/* *******************************************************
98* Memory operations
99**********************************************************/
100static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }
101
102
Yann Collet5be2dd22015-11-11 13:43:58 +0100103/* *************************************
104* 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 Collet5be2dd22015-11-11 13:43:58 +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;
139 ZSTD_parameters params;
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 Collet88fcd292015-11-25 14:42:45 +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;
inikepa4dde252016-03-01 14:14:35 +0100162 dctx->params.searchLength = MINMATCH; /* overwritten by frame but forces ZSTD_btopt to MINMATCH in block mode */
163 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
188/* *************************************************************
189* 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
195 - 4 bytes - Magic Number : ZSTD_MAGICNUMBER (defined within zstd_internal.h)
196 - 1 byte - Window Descriptor
197 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
206/* Block format description
Yann Colletfb810d62016-01-28 00:18:06 +0100207
208 Block = Literal Section - Sequences Section
209 Prerequisite : size of (compressed) block, maximum size of regenerated data
210
Yann Collet59d1f792016-01-23 19:28:41 +0100211 1) Literal Section
Yann Colletfb810d62016-01-28 00:18:06 +0100212
213 1.1) Header : 1-5 bytes
214 flags: 2 bits
Yann Collet59d1f792016-01-23 19:28:41 +0100215 00 compressed by Huff0
Yann Colletfb810d62016-01-28 00:18:06 +0100216 01 unused
217 10 is Raw (uncompressed)
218 11 is Rle
219 Note : using 01 => Huff0 with precomputed table ?
Yann Collet59d1f792016-01-23 19:28:41 +0100220 Note : delta map ? => compressed ?
Yann Colletfb810d62016-01-28 00:18:06 +0100221
222 1.1.1) Huff0-compressed literal block : 3-5 bytes
223 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
224 srcSize < 1 KB => 3 bytes (2-2-10-10)
225 srcSize < 16KB => 4 bytes (2-2-14-14)
226 else => 5 bytes (2-2-18-18)
227 big endian convention
228
229 1.1.2) Raw (uncompressed) literal block header : 1-3 bytes
230 size : 5 bits: (IS_RAW<<6) + (0<<4) + size
231 12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)
232 size&255
233 20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)
234 size>>8&255
235 size&255
236
237 1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes
238 size : 5 bits: (IS_RLE<<6) + (0<<4) + size
239 12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)
240 size&255
241 20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)
242 size>>8&255
243 size&255
244
245 1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes
246 srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream
247 srcSize < 1 KB => 3 bytes (2-2-10-10)
248 srcSize < 16KB => 4 bytes (2-2-14-14)
249 else => 5 bytes (2-2-18-18)
250 big endian convention
251
252 1- CTable available (stored into workspace ?)
253 2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)
254
255
256 1.2) Literal block content
Yann Collet59d1f792016-01-23 19:28:41 +0100257
258 1.2.1) Huff0 block, using sizes from header
259 See Huff0 format
260
Yann Colletfb810d62016-01-28 00:18:06 +0100261 1.2.2) Huff0 block, using prepared table
Yann Collet59d1f792016-01-23 19:28:41 +0100262
Yann Colletfb810d62016-01-28 00:18:06 +0100263 1.2.3) Raw content
264
265 1.2.4) single byte
266
Yann Collet59d1f792016-01-23 19:28:41 +0100267
268 2) Sequences section
269 TO DO
270*/
271
272
Yann Collet953ce722016-02-04 15:28:14 +0100273/** ZSTD_decodeFrameHeader_Part1() :
Yann Collet88fcd292015-11-25 14:42:45 +0100274* decode the 1st part of the Frame Header, which tells Frame Header size.
Yann Collet953ce722016-02-04 15:28:14 +0100275* srcSize must be == ZSTD_frameHeaderSize_min.
Yann Collet88fcd292015-11-25 14:42:45 +0100276* @return : the full size of the Frame Header */
277static size_t ZSTD_decodeFrameHeader_Part1(ZSTD_DCtx* zc, const void* src, size_t srcSize)
278{
279 U32 magicNumber;
Yann Collet61e16ce2016-01-31 02:04:15 +0100280 if (srcSize != ZSTD_frameHeaderSize_min)
281 return ERROR(srcSize_wrong);
Yann Collet88fcd292015-11-25 14:42:45 +0100282 magicNumber = MEM_readLE32(src);
283 if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
284 zc->headerSize = ZSTD_frameHeaderSize_min;
285 return zc->headerSize;
286}
287
Yann Collet88fcd292015-11-25 14:42:45 +0100288
289size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize)
290{
291 U32 magicNumber;
292 if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_max;
293 magicNumber = MEM_readLE32(src);
294 if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);
295 memset(params, 0, sizeof(*params));
Yann Collet26415d32015-11-26 12:43:28 +0100296 params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
inikep6b3739c2016-02-22 15:53:42 +0100297 params->searchLength = (((const BYTE*)src)[4] & 16) ? MINMATCH-1 : MINMATCH;
298 if ((((const BYTE*)src)[4] >> 5) != 0) return ERROR(frameParameter_unsupported); /* reserved 3 bits */
Yann Collet88fcd292015-11-25 14:42:45 +0100299 return 0;
300}
301
Yann Collet953ce722016-02-04 15:28:14 +0100302/** ZSTD_decodeFrameHeader_Part2() :
303* decode the full Frame Header.
304* srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1().
Yann Collet26415d32015-11-26 12:43:28 +0100305* @return : 0, or an error code, which can be tested using ZSTD_isError() */
306static size_t ZSTD_decodeFrameHeader_Part2(ZSTD_DCtx* zc, const void* src, size_t srcSize)
307{
Yann Collet00fd7a22015-11-28 16:03:22 +0100308 size_t result;
Yann Collet61e16ce2016-01-31 02:04:15 +0100309 if (srcSize != zc->headerSize)
310 return ERROR(srcSize_wrong);
Yann Collet00fd7a22015-11-28 16:03:22 +0100311 result = ZSTD_getFrameParams(&(zc->params), src, srcSize);
Yann Collet72bff502016-02-03 12:06:24 +0100312 if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupportedBy32bits);
Yann Collet00fd7a22015-11-28 16:03:22 +0100313 return result;
Yann Collet26415d32015-11-26 12:43:28 +0100314}
315
Yann Collet5be2dd22015-11-11 13:43:58 +0100316
317size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)
318{
319 const BYTE* const in = (const BYTE* const)src;
320 BYTE headerFlags;
321 U32 cSize;
322
Yann Collet61e16ce2016-01-31 02:04:15 +0100323 if (srcSize < 3)
324 return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100325
326 headerFlags = *in;
327 cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);
328
329 bpPtr->blockType = (blockType_t)(headerFlags >> 6);
330 bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;
331
332 if (bpPtr->blockType == bt_end) return 0;
333 if (bpPtr->blockType == bt_rle) return 1;
334 return cSize;
335}
336
Yann Collet59d1f792016-01-23 19:28:41 +0100337
Yann Collet0f366c62015-11-12 16:19:30 +0100338static size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100339{
340 if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);
341 memcpy(dst, src, srcSize);
342 return srcSize;
343}
344
345
Yann Collet953ce722016-02-04 15:28:14 +0100346/*! ZSTD_decodeLiteralsBlock() :
Yann Collet14983e72015-11-11 21:38:21 +0100347 @return : nb of bytes read from src (< srcSize ) */
Yann Collet5b78d2f2015-11-12 15:36:05 +0100348size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
Yann Collet5be2dd22015-11-11 13:43:58 +0100349 const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
350{
Yann Collet5be2dd22015-11-11 13:43:58 +0100351 const BYTE* const istart = (const BYTE*) src;
352
353 /* any compressed block with literals segment must be at least this size */
354 if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);
355
Yann Collet59d1f792016-01-23 19:28:41 +0100356 switch(istart[0]>> 6)
Yann Collet5be2dd22015-11-11 13:43:58 +0100357 {
Yann Collet59d1f792016-01-23 19:28:41 +0100358 case IS_HUF:
Yann Collet5be2dd22015-11-11 13:43:58 +0100359 {
Yann Colletafe07092016-01-25 04:10:46 +0100360 size_t litSize, litCSize, singleStream=0;
Yann Collet59d1f792016-01-23 19:28:41 +0100361 U32 lhSize = ((istart[0]) >> 4) & 3;
362 switch(lhSize)
363 {
364 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
365 /* 2 - 2 - 10 - 10 */
366 lhSize=3;
Yann Colletafe07092016-01-25 04:10:46 +0100367 singleStream = istart[0] & 16;
Yann Collet59d1f792016-01-23 19:28:41 +0100368 litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
369 litCSize = ((istart[1] & 3) << 8) + istart[2];
370 break;
371 case 2:
372 /* 2 - 2 - 14 - 14 */
373 lhSize=4;
374 litSize = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);
375 litCSize = ((istart[2] & 63) << 8) + istart[3];
376 break;
377 case 3:
378 /* 2 - 2 - 18 - 18 */
379 lhSize=5;
380 litSize = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);
381 litCSize = ((istart[2] & 3) << 16) + (istart[3] << 8) + istart[4];
382 break;
383 }
Yann Colletfb810d62016-01-28 00:18:06 +0100384 if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100385
Yann Colletafe07092016-01-25 04:10:46 +0100386 if (HUF_isError(singleStream ?
387 HUF_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :
388 HUF_decompress (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))
Yann Collet59d1f792016-01-23 19:28:41 +0100389 return ERROR(corruption_detected);
390
Yann Collet5be2dd22015-11-11 13:43:58 +0100391 dctx->litPtr = dctx->litBuffer;
392 dctx->litBufSize = BLOCKSIZE+8;
393 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100394 return litCSize + lhSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100395 }
Yann Colletb923f652016-01-26 03:14:20 +0100396 case IS_PCH:
397 {
398 size_t errorCode;
399 size_t litSize, litCSize;
400 U32 lhSize = ((istart[0]) >> 4) & 3;
401 if (lhSize != 1) /* only case supported for now : small litSize, single stream */
402 return ERROR(corruption_detected);
Yann Colletfb810d62016-01-28 00:18:06 +0100403 if (!dctx->flagStaticTables)
Yann Collet7b51a292016-01-26 15:58:49 +0100404 return ERROR(dictionary_corrupted);
Yann Colletb923f652016-01-26 03:14:20 +0100405
406 /* 2 - 2 - 10 - 10 */
407 lhSize=3;
408 litSize = ((istart[0] & 15) << 6) + (istart[1] >> 2);
409 litCSize = ((istart[1] & 3) << 8) + istart[2];
410
411 errorCode = HUF_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);
412 if (HUF_isError(errorCode)) return ERROR(corruption_detected);
413
414 dctx->litPtr = dctx->litBuffer;
415 dctx->litBufSize = BLOCKSIZE+WILDCOPY_OVERLENGTH;
416 dctx->litSize = litSize;
417 return litCSize + lhSize;
418 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100419 case IS_RAW:
420 {
Yann Collet59d1f792016-01-23 19:28:41 +0100421 size_t litSize;
422 U32 lhSize = ((istart[0]) >> 4) & 3;
423 switch(lhSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100424 {
Yann Collet59d1f792016-01-23 19:28:41 +0100425 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
426 lhSize=1;
427 litSize = istart[0] & 31;
428 break;
429 case 2:
430 litSize = ((istart[0] & 15) << 8) + istart[1];
431 break;
432 case 3:
433 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
434 break;
435 }
436
Yann Collet61e16ce2016-01-31 02:04:15 +0100437 if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
Yann Colletb010b3b2016-02-03 12:39:34 +0100438 if (litSize+lhSize > srcSize) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100439 memcpy(dctx->litBuffer, istart+lhSize, litSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100440 dctx->litPtr = dctx->litBuffer;
441 dctx->litBufSize = BLOCKSIZE+8;
442 dctx->litSize = litSize;
Yann Colletbc4c8aa2016-01-25 17:26:01 +0100443 return lhSize+litSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100444 }
445 /* direct reference into compressed stream */
Yann Collet59d1f792016-01-23 19:28:41 +0100446 dctx->litPtr = istart+lhSize;
447 dctx->litBufSize = srcSize-lhSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100448 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100449 return lhSize+litSize;
450 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100451 case IS_RLE:
452 {
Yann Collet59d1f792016-01-23 19:28:41 +0100453 size_t litSize;
454 U32 lhSize = ((istart[0]) >> 4) & 3;
455 switch(lhSize)
456 {
457 case 0: case 1: default: /* note : default is impossible, since lhSize into [0..3] */
458 lhSize = 1;
459 litSize = istart[0] & 31;
460 break;
461 case 2:
462 litSize = ((istart[0] & 15) << 8) + istart[1];
463 break;
464 case 3:
465 litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];
466 break;
467 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100468 if (litSize > BLOCKSIZE) return ERROR(corruption_detected);
Yann Collet59d1f792016-01-23 19:28:41 +0100469 memset(dctx->litBuffer, istart[lhSize], litSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100470 dctx->litPtr = dctx->litBuffer;
Yann Colletb923f652016-01-26 03:14:20 +0100471 dctx->litBufSize = BLOCKSIZE+WILDCOPY_OVERLENGTH;
Yann Collet5be2dd22015-11-11 13:43:58 +0100472 dctx->litSize = litSize;
Yann Collet59d1f792016-01-23 19:28:41 +0100473 return lhSize+1;
Yann Collet5be2dd22015-11-11 13:43:58 +0100474 }
Yann Colletb923f652016-01-26 03:14:20 +0100475 default:
476 return ERROR(corruption_detected); /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100477 }
478}
479
480
481size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,
482 FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,
483 const void* src, size_t srcSize)
484{
485 const BYTE* const istart = (const BYTE* const)src;
486 const BYTE* ip = istart;
487 const BYTE* const iend = istart + srcSize;
488 U32 LLtype, Offtype, MLtype;
489 U32 LLlog, Offlog, MLlog;
490 size_t dumpsLength;
491
492 /* check */
Yann Collet61e16ce2016-01-31 02:04:15 +0100493 if (srcSize < MIN_SEQUENCES_SIZE)
494 return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100495
496 /* SeqHead */
Yann Collet61e16ce2016-01-31 02:04:15 +0100497 *nbSeq = *ip++;
498 if (*nbSeq==0) return 1;
Yann Colletd409db62016-03-04 14:45:31 +0100499 if (*nbSeq >= 0x7F) {
500 if (*nbSeq == 0xFF)
501 *nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;
502 else
503 *nbSeq = ((nbSeq[0]-0x80)<<8) + *ip++;
504 }
Yann Collete93d6ce2016-01-31 00:58:06 +0100505
Yann Colletd409db62016-03-04 14:45:31 +0100506 /* FSE table descriptors */
Yann Collet5be2dd22015-11-11 13:43:58 +0100507 LLtype = *ip >> 6;
508 Offtype = (*ip >> 4) & 3;
509 MLtype = (*ip >> 2) & 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100510 if (*ip & 2) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100511 dumpsLength = ip[2];
512 dumpsLength += ip[1] << 8;
513 ip += 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100514 } else {
Yann Collet5be2dd22015-11-11 13:43:58 +0100515 dumpsLength = ip[1];
516 dumpsLength += (ip[0] & 1) << 8;
517 ip += 2;
518 }
519 *dumpsPtr = ip;
520 ip += dumpsLength;
521 *dumpsLengthPtr = dumpsLength;
522
523 /* check */
524 if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
525
526 /* sequences */
527 {
Yann Collet82368cf2015-11-16 19:10:56 +0100528 S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL >= MaxOff */
Yann Collet5be2dd22015-11-11 13:43:58 +0100529 size_t headerSize;
530
531 /* Build DTables */
532 switch(LLtype)
533 {
534 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100535 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100536 LLlog = 0;
Yann Colletfb810d62016-01-28 00:18:06 +0100537 FSE_buildDTable_rle(DTableLL, *ip++);
538 break;
539 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100540 LLlog = LLbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100541 FSE_buildDTable_raw(DTableLL, LLbits);
542 break;
543 case FSE_ENCODING_STATIC:
544 break;
545 case FSE_ENCODING_DYNAMIC :
546 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100547 max = MaxLL;
548 headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
549 if (FSE_isError(headerSize)) return ERROR(GENERIC);
550 if (LLlog > LLFSELog) return ERROR(corruption_detected);
551 ip += headerSize;
552 FSE_buildDTable(DTableLL, norm, max, LLlog);
553 }
554
555 switch(Offtype)
556 {
557 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100558 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100559 Offlog = 0;
560 if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
561 FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */
562 break;
Yann Colletfb810d62016-01-28 00:18:06 +0100563 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100564 Offlog = Offbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100565 FSE_buildDTable_raw(DTableOffb, Offbits);
566 break;
567 case FSE_ENCODING_STATIC:
568 break;
569 case FSE_ENCODING_DYNAMIC :
570 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100571 max = MaxOff;
572 headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
573 if (FSE_isError(headerSize)) return ERROR(GENERIC);
574 if (Offlog > OffFSELog) return ERROR(corruption_detected);
575 ip += headerSize;
576 FSE_buildDTable(DTableOffb, norm, max, Offlog);
577 }
578
579 switch(MLtype)
580 {
581 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100582 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100583 MLlog = 0;
584 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 +0100585 FSE_buildDTable_rle(DTableML, *ip++);
586 break;
587 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100588 MLlog = MLbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100589 FSE_buildDTable_raw(DTableML, MLbits);
590 break;
591 case FSE_ENCODING_STATIC:
592 break;
593 case FSE_ENCODING_DYNAMIC :
594 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100595 max = MaxML;
596 headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
597 if (FSE_isError(headerSize)) return ERROR(GENERIC);
598 if (MLlog > MLFSELog) return ERROR(corruption_detected);
599 ip += headerSize;
600 FSE_buildDTable(DTableML, norm, max, MLlog);
Yann Colletfb810d62016-01-28 00:18:06 +0100601 } }
Yann Collet5be2dd22015-11-11 13:43:58 +0100602
603 return ip-istart;
604}
605
606
607typedef struct {
608 size_t litLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100609 size_t matchLength;
Yann Collete93d6ce2016-01-31 00:58:06 +0100610 size_t offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100611} seq_t;
612
613typedef struct {
614 BIT_DStream_t DStream;
615 FSE_DState_t stateLL;
616 FSE_DState_t stateOffb;
617 FSE_DState_t stateML;
618 size_t prevOffset;
619 const BYTE* dumps;
620 const BYTE* dumpsEnd;
621} seqState_t;
622
inikepe9f30ea2016-02-03 12:53:07 +0100623
624
inikep6b3739c2016-02-22 15:53:42 +0100625static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
Yann Collet5be2dd22015-11-11 13:43:58 +0100626{
627 size_t litLength;
628 size_t prevOffset;
629 size_t offset;
630 size_t matchLength;
631 const BYTE* dumps = seqState->dumps;
632 const BYTE* const de = seqState->dumpsEnd;
633
634 /* Literal length */
Yann Collete93d6ce2016-01-31 00:58:06 +0100635 litLength = FSE_peakSymbol(&(seqState->stateLL));
Yann Collete4fdad52015-11-25 21:09:17 +0100636 prevOffset = litLength ? seq->offset : seqState->prevOffset;
Yann Colletfb810d62016-01-28 00:18:06 +0100637 if (litLength == MaxLL) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100638 U32 add = *dumps++;
639 if (add < 255) litLength += add;
Yann Colletfb810d62016-01-28 00:18:06 +0100640 else {
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100641 litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no risk : dumps is always followed by seq tables > 1 byte */
642 if (litLength&1) litLength>>=1, dumps += 3;
643 else litLength = (U16)(litLength)>>1, dumps += 2;
Yann Collet5be2dd22015-11-11 13:43:58 +0100644 }
645 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
646 }
647
648 /* Offset */
649 {
650 static const U32 offsetPrefix[MaxOff+1] = {
651 1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,
652 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
653 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };
Yann Collete93d6ce2016-01-31 00:58:06 +0100654 U32 offsetCode = FSE_peakSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
655 U32 nbBits = offsetCode - 1;
Yann Collet5be2dd22015-11-11 13:43:58 +0100656 if (offsetCode==0) nbBits = 0; /* cmove */
657 offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);
658 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
Yann Collete93d6ce2016-01-31 00:58:06 +0100659 if (offsetCode==0) offset = prevOffset; /* repcode, cmove */
Yann Collet55aa7f92015-11-20 12:04:52 +0100660 if (offsetCode | !litLength) seqState->prevOffset = seq->offset; /* cmove */
Yann Collete93d6ce2016-01-31 00:58:06 +0100661 FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* update */
Yann Collet5be2dd22015-11-11 13:43:58 +0100662 }
663
Yann Collete93d6ce2016-01-31 00:58:06 +0100664 /* Literal length update */
665 FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); /* update */
666 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
667
Yann Collet5be2dd22015-11-11 13:43:58 +0100668 /* MatchLength */
669 matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
Yann Colletfb810d62016-01-28 00:18:06 +0100670 if (matchLength == MaxML) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100671 U32 add = *dumps++;
672 if (add < 255) matchLength += add;
Yann Colletfb810d62016-01-28 00:18:06 +0100673 else {
Yann Collet5be2dd22015-11-11 13:43:58 +0100674 matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100675 if (matchLength&1) matchLength>>=1, dumps += 3;
676 else matchLength = (U16)(matchLength)>>1, dumps += 2;
Yann Collet5be2dd22015-11-11 13:43:58 +0100677 }
678 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
679 }
inikep6b3739c2016-02-22 15:53:42 +0100680 matchLength += mls;
Yann Collet5be2dd22015-11-11 13:43:58 +0100681
682 /* save result */
683 seq->litLength = litLength;
684 seq->offset = offset;
685 seq->matchLength = matchLength;
686 seqState->dumps = dumps;
Yann Colletfb810d62016-01-28 00:18:06 +0100687
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100688#if 0 /* debug */
Yann Colletfb810d62016-01-28 00:18:06 +0100689 {
690 static U64 totalDecoded = 0;
691 printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
692 (U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);
693 totalDecoded += litLength + matchLength;
694 }
695#endif
Yann Collet5be2dd22015-11-11 13:43:58 +0100696}
697
698
Yann Collet5b78d2f2015-11-12 15:36:05 +0100699FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
Yann Colletb3a2af92015-11-19 17:13:19 +0100700 BYTE* const oend, seq_t sequence,
Yann Collet5be2dd22015-11-11 13:43:58 +0100701 const BYTE** litPtr, const BYTE* const litLimit_8,
Yann Collet417890c2015-12-04 17:16:37 +0100702 const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
Yann Collet5be2dd22015-11-11 13:43:58 +0100703{
Yann Colletb3a2af92015-11-19 17:13:19 +0100704 static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
705 static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
Yann Collet5be2dd22015-11-11 13:43:58 +0100706 BYTE* const oLitEnd = op + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100707 const size_t sequenceLength = sequence.litLength + sequence.matchLength;
708 BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
Yann Collet5be2dd22015-11-11 13:43:58 +0100709 BYTE* const oend_8 = oend-8;
710 const BYTE* const litEnd = *litPtr + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100711 const BYTE* match = oLitEnd - sequence.offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100712
713 /* check */
714 if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
715 if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
716 if (litEnd > litLimit_8) return ERROR(corruption_detected); /* risk read beyond lit buffer */
717
718 /* copy Literals */
719 ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
720 op = oLitEnd;
721 *litPtr = litEnd; /* update for next sequence */
722
723 /* copy Match */
Yann Collet7b51a292016-01-26 15:58:49 +0100724 if (sequence.offset > (size_t)(oLitEnd - base)) {
Yann Collet44287a32015-11-30 23:13:56 +0100725 /* offset beyond prefix */
Yann Collet9f5ab1a2015-12-11 00:27:41 +0100726 if (sequence.offset > (size_t)(oLitEnd - vBase))
727 return ERROR(corruption_detected);
Yann Collet44287a32015-11-30 23:13:56 +0100728 match = dictEnd - (base-match);
Yann Collet7b51a292016-01-26 15:58:49 +0100729 if (match + sequence.matchLength <= dictEnd) {
Yann Collet4bfe4152015-12-06 13:18:37 +0100730 memmove(oLitEnd, match, sequence.matchLength);
Yann Collet44287a32015-11-30 23:13:56 +0100731 return sequenceLength;
732 }
733 /* span extDict & currentPrefixSegment */
734 {
735 size_t length1 = dictEnd - match;
Yann Collet4bfe4152015-12-06 13:18:37 +0100736 memmove(oLitEnd, match, length1);
Yann Collet44287a32015-11-30 23:13:56 +0100737 op = oLitEnd + length1;
738 sequence.matchLength -= length1;
739 match = base;
Yann Colletfb810d62016-01-28 00:18:06 +0100740 } }
Yann Collet0f366c62015-11-12 16:19:30 +0100741
Yann Collet44287a32015-11-30 23:13:56 +0100742 /* match within prefix */
Yann Collet7b51a292016-01-26 15:58:49 +0100743 if (sequence.offset < 8) {
Yann Collet44287a32015-11-30 23:13:56 +0100744 /* close range match, overlap */
745 const int sub2 = dec64table[sequence.offset];
746 op[0] = match[0];
747 op[1] = match[1];
748 op[2] = match[2];
749 op[3] = match[3];
750 match += dec32table[sequence.offset];
751 ZSTD_copy4(op+4, match);
752 match -= sub2;
Yann Colletfb810d62016-01-28 00:18:06 +0100753 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100754 ZSTD_copy8(op, match);
755 }
756 op += 8; match += 8;
Yann Collet5be2dd22015-11-11 13:43:58 +0100757
inikepa4dde252016-03-01 14:14:35 +0100758 if (oMatchEnd > oend-(16-3)) { // 3 = MINMATCH
Yann Collet7b51a292016-01-26 15:58:49 +0100759 if (op < oend_8) {
Yann Collet44287a32015-11-30 23:13:56 +0100760 ZSTD_wildcopy(op, match, oend_8 - op);
761 match += oend_8 - op;
762 op = oend_8;
763 }
Yann Colletfb810d62016-01-28 00:18:06 +0100764 while (op < oMatchEnd)
765 *op++ = *match++;
766 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100767 ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
768 }
769 return sequenceLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100770}
771
Yann Colletb3a2af92015-11-19 17:13:19 +0100772
Yann Collet5be2dd22015-11-11 13:43:58 +0100773static size_t ZSTD_decompressSequences(
Yann Collet5b78d2f2015-11-12 15:36:05 +0100774 ZSTD_DCtx* dctx,
Yann Collet5be2dd22015-11-11 13:43:58 +0100775 void* dst, size_t maxDstSize,
776 const void* seqStart, size_t seqSize)
777{
Yann Collet5be2dd22015-11-11 13:43:58 +0100778 const BYTE* ip = (const BYTE*)seqStart;
779 const BYTE* const iend = ip + seqSize;
780 BYTE* const ostart = (BYTE* const)dst;
781 BYTE* op = ostart;
782 BYTE* const oend = ostart + maxDstSize;
783 size_t errorCode, dumpsLength;
784 const BYTE* litPtr = dctx->litPtr;
785 const BYTE* const litLimit_8 = litPtr + dctx->litBufSize - 8;
786 const BYTE* const litEnd = litPtr + dctx->litSize;
787 int nbSeq;
788 const BYTE* dumps;
789 U32* DTableLL = dctx->LLTable;
790 U32* DTableML = dctx->MLTable;
791 U32* DTableOffb = dctx->OffTable;
Yann Collet417890c2015-12-04 17:16:37 +0100792 const BYTE* const base = (const BYTE*) (dctx->base);
793 const BYTE* const vBase = (const BYTE*) (dctx->vBase);
794 const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
inikep6b3739c2016-02-22 15:53:42 +0100795 const U32 mls = dctx->params.searchLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100796
797 /* Build Decoding Tables */
798 errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
799 DTableLL, DTableML, DTableOffb,
Yann Colletfb810d62016-01-28 00:18:06 +0100800 ip, seqSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100801 if (ZSTD_isError(errorCode)) return errorCode;
802 ip += errorCode;
803
804 /* Regen sequences */
Yann Collete93d6ce2016-01-31 00:58:06 +0100805 if (nbSeq) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100806 seq_t sequence;
807 seqState_t seqState;
808
809 memset(&sequence, 0, sizeof(sequence));
Yann Collet61e16ce2016-01-31 02:04:15 +0100810 sequence.offset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100811 seqState.dumps = dumps;
812 seqState.dumpsEnd = dumps + dumpsLength;
Yann Collet61e16ce2016-01-31 02:04:15 +0100813 seqState.prevOffset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100814 errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
815 if (ERR_isError(errorCode)) return ERROR(corruption_detected);
816 FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
817 FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
818 FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
819
Yann Collet7b51a292016-01-26 15:58:49 +0100820 for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
Yann Colletb3a2af92015-11-19 17:13:19 +0100821 size_t oneSeqSize;
822 nbSeq--;
inikep6b3739c2016-02-22 15:53:42 +0100823 ZSTD_decodeSequence(&sequence, &seqState, mls);
Yann Colletb3a2af92015-11-19 17:13:19 +0100824 oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_8, base, vBase, dictEnd);
Yann Collet5be2dd22015-11-11 13:43:58 +0100825 if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
826 op += oneSeqSize;
827 }
828
829 /* check if reached exact end */
Yann Collet35f7de52016-01-31 02:51:03 +0100830 if (nbSeq) return ERROR(corruption_detected);
Yann Collete93d6ce2016-01-31 00:58:06 +0100831 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100832
Yann Collete93d6ce2016-01-31 00:58:06 +0100833 /* last literal segment */
834 {
835 size_t lastLLSize = litEnd - litPtr;
836 if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */
837 if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
838 memcpy(op, litPtr, lastLLSize);
839 op += lastLLSize;
840 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100841
842 return op-ostart;
843}
844
845
Yann Colletb0125102016-01-09 02:00:10 +0100846static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
847{
Yann Collet7b51a292016-01-26 15:58:49 +0100848 if (dst != dctx->previousDstEnd) { /* not contiguous */
Yann Colletb0125102016-01-09 02:00:10 +0100849 dctx->dictEnd = dctx->previousDstEnd;
850 dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
851 dctx->base = dst;
852 dctx->previousDstEnd = dst;
853 }
854}
855
856
857static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100858 void* dst, size_t dstCapacity,
Yann Collet5be2dd22015-11-11 13:43:58 +0100859 const void* src, size_t srcSize)
Yann Colletb010b3b2016-02-03 12:39:34 +0100860{ /* blockType == blockCompressed */
Yann Collet5be2dd22015-11-11 13:43:58 +0100861 const BYTE* ip = (const BYTE*)src;
Yann Colletb010b3b2016-02-03 12:39:34 +0100862 size_t litCSize;
863
864 if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100865
inikepa4dde252016-03-01 14:14:35 +0100866 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBlock_internal searchLength=%d\n", dctx->base, dctx->params.searchLength);
867
Yann Collet5be2dd22015-11-11 13:43:58 +0100868 /* Decode literals sub-block */
Yann Colletb010b3b2016-02-03 12:39:34 +0100869 litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100870 if (ZSTD_isError(litCSize)) return litCSize;
871 ip += litCSize;
872 srcSize -= litCSize;
873
Yann Colletb010b3b2016-02-03 12:39:34 +0100874 return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100875}
876
877
Yann Colletb0125102016-01-09 02:00:10 +0100878size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100879 void* dst, size_t dstCapacity,
Yann Colletb0125102016-01-09 02:00:10 +0100880 const void* src, size_t srcSize)
881{
882 ZSTD_checkContinuity(dctx, dst);
Yann Colletb010b3b2016-02-03 12:39:34 +0100883 return ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
Yann Colletb0125102016-01-09 02:00:10 +0100884}
885
886
Yann Collet7b51a292016-01-26 15:58:49 +0100887/*! ZSTD_decompress_continueDCtx
888* dctx must have been properly initialized */
889static size_t ZSTD_decompress_continueDCtx(ZSTD_DCtx* dctx,
Yann Collet31683c02015-12-18 01:26:48 +0100890 void* dst, size_t maxDstSize,
Yann Collet7b51a292016-01-26 15:58:49 +0100891 const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100892{
893 const BYTE* ip = (const BYTE*)src;
894 const BYTE* iend = ip + srcSize;
895 BYTE* const ostart = (BYTE* const)dst;
896 BYTE* op = ostart;
897 BYTE* const oend = ostart + maxDstSize;
898 size_t remainingSize = srcSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100899 blockProperties_t blockProperties;
900
901 /* Frame Header */
Yann Collet88fcd292015-11-25 14:42:45 +0100902 {
903 size_t frameHeaderSize;
904 if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100905#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
Yann Collet88fcd292015-11-25 14:42:45 +0100906 {
907 const U32 magicNumber = MEM_readLE32(src);
908 if (ZSTD_isLegacy(magicNumber))
909 return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber);
910 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100911#endif
Yann Collet37422192016-01-25 16:54:05 +0100912 frameHeaderSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min);
Yann Collet88fcd292015-11-25 14:42:45 +0100913 if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
914 if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
915 ip += frameHeaderSize; remainingSize -= frameHeaderSize;
Yann Collet37422192016-01-25 16:54:05 +0100916 frameHeaderSize = ZSTD_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);
Yann Collet88fcd292015-11-25 14:42:45 +0100917 if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
918 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100919
920 /* Loop on each block */
921 while (1)
922 {
923 size_t decodedSize=0;
924 size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
925 if (ZSTD_isError(cBlockSize)) return cBlockSize;
926
927 ip += ZSTD_blockHeaderSize;
928 remainingSize -= ZSTD_blockHeaderSize;
929 if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
930
931 switch(blockProperties.blockType)
932 {
933 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +0100934 decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100935 break;
936 case bt_raw :
Yann Collet0f366c62015-11-12 16:19:30 +0100937 decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100938 break;
939 case bt_rle :
940 return ERROR(GENERIC); /* not yet supported */
941 break;
942 case bt_end :
943 /* end of frame */
944 if (remainingSize) return ERROR(srcSize_wrong);
945 break;
946 default:
947 return ERROR(GENERIC); /* impossible */
948 }
949 if (cBlockSize == 0) break; /* bt_end */
950
951 if (ZSTD_isError(decodedSize)) return decodedSize;
952 op += decodedSize;
953 ip += cBlockSize;
954 remainingSize -= cBlockSize;
955 }
956
957 return op-ostart;
958}
959
Yann Collet31683c02015-12-18 01:26:48 +0100960
Yann Collet7b51a292016-01-26 15:58:49 +0100961size_t ZSTD_decompress_usingPreparedDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* refDCtx,
962 void* dst, size_t maxDstSize,
963 const void* src, size_t srcSize)
964{
965 ZSTD_copyDCtx(dctx, refDCtx);
966 ZSTD_checkContinuity(dctx, dst);
967 return ZSTD_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);
968}
969
970
971size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
972 void* dst, size_t maxDstSize,
973 const void* src, size_t srcSize,
974 const void* dict, size_t dictSize)
975{
976 ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
inikepa4dde252016-03-01 14:14:35 +0100977 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin_usingDict searchLength=%d\n", dctx->base, dctx->params.searchLength);
Yann Collet7b51a292016-01-26 15:58:49 +0100978 ZSTD_checkContinuity(dctx, dst);
979 return ZSTD_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);
980}
981
982
Yann Collet31683c02015-12-18 01:26:48 +0100983size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
984{
985 return ZSTD_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);
986}
987
Yann Collet5be2dd22015-11-11 13:43:58 +0100988size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
989{
Yann Collet3a3b72f2016-01-11 12:56:11 +0100990#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
991 size_t regenSize;
992 ZSTD_DCtx* dctx = ZSTD_createDCtx();
993 if (dctx==NULL) return ERROR(memory_allocation);
994 regenSize = ZSTD_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);
995 ZSTD_freeDCtx(dctx);
996 return regenSize;
997#else
Yann Collet31683c02015-12-18 01:26:48 +0100998 ZSTD_DCtx dctx;
999 return ZSTD_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);
Yann Colleta768a302016-01-21 16:04:35 +01001000#endif
Yann Collet5be2dd22015-11-11 13:43:58 +01001001}
1002
1003
1004/* ******************************
1005* Streaming Decompression API
1006********************************/
Yann Collet5be2dd22015-11-11 13:43:58 +01001007size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)
1008{
1009 return dctx->expected;
1010}
1011
Yann Collet37422192016-01-25 16:54:05 +01001012size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +01001013{
1014 /* Sanity check */
Yann Collet37422192016-01-25 16:54:05 +01001015 if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
1016 ZSTD_checkContinuity(dctx, dst);
Yann Collet5be2dd22015-11-11 13:43:58 +01001017
Yann Collet88fcd292015-11-25 14:42:45 +01001018 /* Decompress : frame header; part 1 */
Yann Collet37422192016-01-25 16:54:05 +01001019 switch (dctx->stage)
Yann Collet5be2dd22015-11-11 13:43:58 +01001020 {
Yann Collet88fcd292015-11-25 14:42:45 +01001021 case ZSTDds_getFrameHeaderSize :
Yann Collet5be2dd22015-11-11 13:43:58 +01001022 {
Yann Collet88fcd292015-11-25 14:42:45 +01001023 /* get frame header size */
1024 if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
Yann Collet37422192016-01-25 16:54:05 +01001025 dctx->headerSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min);
1026 if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
1027 memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
Yann Collet7b51a292016-01-26 15:58:49 +01001028 if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
Yann Collet37422192016-01-25 16:54:05 +01001029 dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_min;
1030 dctx->stage = ZSTDds_decodeFrameHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001031 return 0;
1032 }
Yann Collet37422192016-01-25 16:54:05 +01001033 dctx->expected = 0; /* not necessary to copy more */
Yann Collet5be2dd22015-11-11 13:43:58 +01001034 }
Yann Collet88fcd292015-11-25 14:42:45 +01001035 case ZSTDds_decodeFrameHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001036 {
Yann Collet88fcd292015-11-25 14:42:45 +01001037 /* get frame header */
1038 size_t result;
Yann Collet37422192016-01-25 16:54:05 +01001039 memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
1040 result = ZSTD_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001041 if (ZSTD_isError(result)) return result;
Yann Collet37422192016-01-25 16:54:05 +01001042 dctx->expected = ZSTD_blockHeaderSize;
1043 dctx->stage = ZSTDds_decodeBlockHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001044 return 0;
Yann Collet5be2dd22015-11-11 13:43:58 +01001045 }
Yann Collet88fcd292015-11-25 14:42:45 +01001046 case ZSTDds_decodeBlockHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001047 {
Yann Collet88fcd292015-11-25 14:42:45 +01001048 /* Decode block header */
1049 blockProperties_t bp;
1050 size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
1051 if (ZSTD_isError(blockSize)) return blockSize;
Yann Collet7b51a292016-01-26 15:58:49 +01001052 if (bp.blockType == bt_end) {
Yann Collet37422192016-01-25 16:54:05 +01001053 dctx->expected = 0;
1054 dctx->stage = ZSTDds_getFrameHeaderSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001055 }
Yann Collet7b51a292016-01-26 15:58:49 +01001056 else {
Yann Collet37422192016-01-25 16:54:05 +01001057 dctx->expected = blockSize;
1058 dctx->bType = bp.blockType;
1059 dctx->stage = ZSTDds_decompressBlock;
Yann Collet88fcd292015-11-25 14:42:45 +01001060 }
Yann Collet88fcd292015-11-25 14:42:45 +01001061 return 0;
1062 }
Yann Collet417890c2015-12-04 17:16:37 +01001063 case ZSTDds_decompressBlock:
Yann Collet88fcd292015-11-25 14:42:45 +01001064 {
1065 /* Decompress : block content */
1066 size_t rSize;
Yann Collet37422192016-01-25 16:54:05 +01001067 switch(dctx->bType)
Yann Collet88fcd292015-11-25 14:42:45 +01001068 {
1069 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +01001070 rSize = ZSTD_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001071 break;
1072 case bt_raw :
1073 rSize = ZSTD_copyRawBlock(dst, maxDstSize, src, srcSize);
1074 break;
1075 case bt_rle :
1076 return ERROR(GENERIC); /* not yet handled */
1077 break;
1078 case bt_end : /* should never happen (filtered at phase 1) */
1079 rSize = 0;
1080 break;
1081 default:
Yann Collet7b51a292016-01-26 15:58:49 +01001082 return ERROR(GENERIC); /* impossible */
Yann Collet88fcd292015-11-25 14:42:45 +01001083 }
Yann Collet37422192016-01-25 16:54:05 +01001084 dctx->stage = ZSTDds_decodeBlockHeader;
1085 dctx->expected = ZSTD_blockHeaderSize;
1086 dctx->previousDstEnd = (char*)dst + rSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001087 return rSize;
1088 }
1089 default:
1090 return ERROR(GENERIC); /* impossible */
1091 }
Yann Collet5be2dd22015-11-11 13:43:58 +01001092}
1093
1094
Yann Colletb923f652016-01-26 03:14:20 +01001095static void ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Collet417890c2015-12-04 17:16:37 +01001096{
Yann Collet37422192016-01-25 16:54:05 +01001097 dctx->dictEnd = dctx->previousDstEnd;
1098 dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
1099 dctx->base = dict;
1100 dctx->previousDstEnd = (const char*)dict + dictSize;
Yann Collet417890c2015-12-04 17:16:37 +01001101}
Yann Colletb923f652016-01-26 03:14:20 +01001102
Yann Colletb923f652016-01-26 03:14:20 +01001103static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1104{
Yann Colletfb810d62016-01-28 00:18:06 +01001105 size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;
1106 short offcodeNCount[MaxOff+1];
1107 U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
1108 short matchlengthNCount[MaxML+1];
1109 unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
1110 short litlengthNCount[MaxLL+1];
1111 unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
1112
1113 hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize);
Yann Colletb923f652016-01-26 03:14:20 +01001114 if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
Yann Colletfb810d62016-01-28 00:18:06 +01001115 dict = (const char*)dict + hSize;
1116 dictSize -= hSize;
1117
1118 offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
1119 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
1120 errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
1121 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1122 dict = (const char*)dict + offcodeHeaderSize;
1123 dictSize -= offcodeHeaderSize;
1124
1125 matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
1126 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
1127 errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
1128 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1129 dict = (const char*)dict + matchlengthHeaderSize;
1130 dictSize -= matchlengthHeaderSize;
1131
1132 litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
1133 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
1134 errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
1135 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1136
1137 dctx->flagStaticTables = 1;
1138 return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
Yann Colletb923f652016-01-26 03:14:20 +01001139}
1140
Yann Collet7b51a292016-01-26 15:58:49 +01001141static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Colletb923f652016-01-26 03:14:20 +01001142{
1143 size_t eSize;
1144 U32 magic = MEM_readLE32(dict);
1145 if (magic != ZSTD_DICT_MAGIC) {
1146 /* pure content mode */
1147 ZSTD_refDictContent(dctx, dict, dictSize);
1148 return 0;
1149 }
1150 /* load entropy tables */
1151 dict = (const char*)dict + 4;
1152 dictSize -= 4;
1153 eSize = ZSTD_loadEntropy(dctx, dict, dictSize);
1154 if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
1155
1156 /* reference dictionary content */
1157 dict = (const char*)dict + eSize;
1158 dictSize -= eSize;
1159 ZSTD_refDictContent(dctx, dict, dictSize);
1160
1161 return 0;
1162}
1163
Yann Collet7b51a292016-01-26 15:58:49 +01001164
1165size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1166{
1167 size_t errorCode;
1168 errorCode = ZSTD_decompressBegin(dctx);
1169 if (ZSTD_isError(errorCode)) return errorCode;
1170
1171 if (dict && dictSize) {
1172 errorCode = ZSTD_decompress_insertDictionary(dctx, dict, dictSize);
1173 if (ZSTD_isError(errorCode)) return ERROR(dictionary_corrupted);
1174 }
1175
1176 return 0;
1177}
1178