blob: e9d3bdb691e271eb8a9df84dfbf7f8634782adaf [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;
499 if (*nbSeq >= 128)
500 *nbSeq = ((nbSeq[0]-128)<<8) + *ip++;
Yann Collete93d6ce2016-01-31 00:58:06 +0100501
Yann Collet5be2dd22015-11-11 13:43:58 +0100502 LLtype = *ip >> 6;
503 Offtype = (*ip >> 4) & 3;
504 MLtype = (*ip >> 2) & 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100505 if (*ip & 2) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100506 dumpsLength = ip[2];
507 dumpsLength += ip[1] << 8;
508 ip += 3;
Yann Colletfb810d62016-01-28 00:18:06 +0100509 } else {
Yann Collet5be2dd22015-11-11 13:43:58 +0100510 dumpsLength = ip[1];
511 dumpsLength += (ip[0] & 1) << 8;
512 ip += 2;
513 }
514 *dumpsPtr = ip;
515 ip += dumpsLength;
516 *dumpsLengthPtr = dumpsLength;
517
518 /* check */
519 if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are "raw", hence no header, but at least xxLog bits per type */
520
521 /* sequences */
522 {
Yann Collet82368cf2015-11-16 19:10:56 +0100523 S16 norm[MaxML+1]; /* assumption : MaxML >= MaxLL >= MaxOff */
Yann Collet5be2dd22015-11-11 13:43:58 +0100524 size_t headerSize;
525
526 /* Build DTables */
527 switch(LLtype)
528 {
529 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100530 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100531 LLlog = 0;
Yann Colletfb810d62016-01-28 00:18:06 +0100532 FSE_buildDTable_rle(DTableLL, *ip++);
533 break;
534 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100535 LLlog = LLbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100536 FSE_buildDTable_raw(DTableLL, LLbits);
537 break;
538 case FSE_ENCODING_STATIC:
539 break;
540 case FSE_ENCODING_DYNAMIC :
541 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100542 max = MaxLL;
543 headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);
544 if (FSE_isError(headerSize)) return ERROR(GENERIC);
545 if (LLlog > LLFSELog) return ERROR(corruption_detected);
546 ip += headerSize;
547 FSE_buildDTable(DTableLL, norm, max, LLlog);
548 }
549
550 switch(Offtype)
551 {
552 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100553 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100554 Offlog = 0;
555 if (ip > iend-2) return ERROR(srcSize_wrong); /* min : "raw", hence no header, but at least xxLog bits */
556 FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */
557 break;
Yann Colletfb810d62016-01-28 00:18:06 +0100558 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100559 Offlog = Offbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100560 FSE_buildDTable_raw(DTableOffb, Offbits);
561 break;
562 case FSE_ENCODING_STATIC:
563 break;
564 case FSE_ENCODING_DYNAMIC :
565 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100566 max = MaxOff;
567 headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);
568 if (FSE_isError(headerSize)) return ERROR(GENERIC);
569 if (Offlog > OffFSELog) return ERROR(corruption_detected);
570 ip += headerSize;
571 FSE_buildDTable(DTableOffb, norm, max, Offlog);
572 }
573
574 switch(MLtype)
575 {
576 U32 max;
Yann Colletfb810d62016-01-28 00:18:06 +0100577 case FSE_ENCODING_RLE :
Yann Collet5be2dd22015-11-11 13:43:58 +0100578 MLlog = 0;
579 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 +0100580 FSE_buildDTable_rle(DTableML, *ip++);
581 break;
582 case FSE_ENCODING_RAW :
Yann Collet5be2dd22015-11-11 13:43:58 +0100583 MLlog = MLbits;
Yann Colletfb810d62016-01-28 00:18:06 +0100584 FSE_buildDTable_raw(DTableML, MLbits);
585 break;
586 case FSE_ENCODING_STATIC:
587 break;
588 case FSE_ENCODING_DYNAMIC :
589 default : /* impossible */
Yann Collet5be2dd22015-11-11 13:43:58 +0100590 max = MaxML;
591 headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);
592 if (FSE_isError(headerSize)) return ERROR(GENERIC);
593 if (MLlog > MLFSELog) return ERROR(corruption_detected);
594 ip += headerSize;
595 FSE_buildDTable(DTableML, norm, max, MLlog);
Yann Colletfb810d62016-01-28 00:18:06 +0100596 } }
Yann Collet5be2dd22015-11-11 13:43:58 +0100597
598 return ip-istart;
599}
600
601
602typedef struct {
603 size_t litLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100604 size_t matchLength;
Yann Collete93d6ce2016-01-31 00:58:06 +0100605 size_t offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100606} seq_t;
607
608typedef struct {
609 BIT_DStream_t DStream;
610 FSE_DState_t stateLL;
611 FSE_DState_t stateOffb;
612 FSE_DState_t stateML;
613 size_t prevOffset;
614 const BYTE* dumps;
615 const BYTE* dumpsEnd;
616} seqState_t;
617
inikepe9f30ea2016-02-03 12:53:07 +0100618
619
inikep6b3739c2016-02-22 15:53:42 +0100620static void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState, const U32 mls)
Yann Collet5be2dd22015-11-11 13:43:58 +0100621{
622 size_t litLength;
623 size_t prevOffset;
624 size_t offset;
625 size_t matchLength;
626 const BYTE* dumps = seqState->dumps;
627 const BYTE* const de = seqState->dumpsEnd;
628
629 /* Literal length */
Yann Collete93d6ce2016-01-31 00:58:06 +0100630 litLength = FSE_peakSymbol(&(seqState->stateLL));
Yann Collete4fdad52015-11-25 21:09:17 +0100631 prevOffset = litLength ? seq->offset : seqState->prevOffset;
Yann Colletfb810d62016-01-28 00:18:06 +0100632 if (litLength == MaxLL) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100633 U32 add = *dumps++;
634 if (add < 255) litLength += add;
Yann Colletfb810d62016-01-28 00:18:06 +0100635 else {
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100636 litLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no risk : dumps is always followed by seq tables > 1 byte */
637 if (litLength&1) litLength>>=1, dumps += 3;
638 else litLength = (U16)(litLength)>>1, dumps += 2;
Yann Collet5be2dd22015-11-11 13:43:58 +0100639 }
640 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
641 }
642
643 /* Offset */
644 {
645 static const U32 offsetPrefix[MaxOff+1] = {
646 1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,
647 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,
648 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };
Yann Collete93d6ce2016-01-31 00:58:06 +0100649 U32 offsetCode = FSE_peakSymbol(&(seqState->stateOffb)); /* <= maxOff, by table construction */
650 U32 nbBits = offsetCode - 1;
Yann Collet5be2dd22015-11-11 13:43:58 +0100651 if (offsetCode==0) nbBits = 0; /* cmove */
652 offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);
653 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
Yann Collete93d6ce2016-01-31 00:58:06 +0100654 if (offsetCode==0) offset = prevOffset; /* repcode, cmove */
Yann Collet55aa7f92015-11-20 12:04:52 +0100655 if (offsetCode | !litLength) seqState->prevOffset = seq->offset; /* cmove */
Yann Collete93d6ce2016-01-31 00:58:06 +0100656 FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream)); /* update */
Yann Collet5be2dd22015-11-11 13:43:58 +0100657 }
658
Yann Collete93d6ce2016-01-31 00:58:06 +0100659 /* Literal length update */
660 FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream)); /* update */
661 if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));
662
Yann Collet5be2dd22015-11-11 13:43:58 +0100663 /* MatchLength */
664 matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));
Yann Colletfb810d62016-01-28 00:18:06 +0100665 if (matchLength == MaxML) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100666 U32 add = *dumps++;
667 if (add < 255) matchLength += add;
Yann Colletfb810d62016-01-28 00:18:06 +0100668 else {
Yann Collet5be2dd22015-11-11 13:43:58 +0100669 matchLength = MEM_readLE32(dumps) & 0xFFFFFF; /* no pb : dumps is always followed by seq tables > 1 byte */
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100670 if (matchLength&1) matchLength>>=1, dumps += 3;
671 else matchLength = (U16)(matchLength)>>1, dumps += 2;
Yann Collet5be2dd22015-11-11 13:43:58 +0100672 }
673 if (dumps >= de) dumps = de-1; /* late correction, to avoid read overflow (data is now corrupted anyway) */
674 }
inikep6b3739c2016-02-22 15:53:42 +0100675 matchLength += mls;
Yann Collet5be2dd22015-11-11 13:43:58 +0100676
677 /* save result */
678 seq->litLength = litLength;
679 seq->offset = offset;
680 seq->matchLength = matchLength;
681 seqState->dumps = dumps;
Yann Colletfb810d62016-01-28 00:18:06 +0100682
Yann Collet7d8e6bd2016-02-02 17:30:37 +0100683#if 0 /* debug */
Yann Colletfb810d62016-01-28 00:18:06 +0100684 {
685 static U64 totalDecoded = 0;
686 printf("pos %6u : %3u literals & match %3u bytes at distance %6u \n",
687 (U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);
688 totalDecoded += litLength + matchLength;
689 }
690#endif
Yann Collet5be2dd22015-11-11 13:43:58 +0100691}
692
693
Yann Collet5b78d2f2015-11-12 15:36:05 +0100694FORCE_INLINE size_t ZSTD_execSequence(BYTE* op,
Yann Colletb3a2af92015-11-19 17:13:19 +0100695 BYTE* const oend, seq_t sequence,
Yann Collet5be2dd22015-11-11 13:43:58 +0100696 const BYTE** litPtr, const BYTE* const litLimit_8,
Yann Collet417890c2015-12-04 17:16:37 +0100697 const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)
Yann Collet5be2dd22015-11-11 13:43:58 +0100698{
Yann Colletb3a2af92015-11-19 17:13:19 +0100699 static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
700 static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* substracted */
Yann Collet5be2dd22015-11-11 13:43:58 +0100701 BYTE* const oLitEnd = op + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100702 const size_t sequenceLength = sequence.litLength + sequence.matchLength;
703 BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
Yann Collet5be2dd22015-11-11 13:43:58 +0100704 BYTE* const oend_8 = oend-8;
705 const BYTE* const litEnd = *litPtr + sequence.litLength;
Yann Colletb3a2af92015-11-19 17:13:19 +0100706 const BYTE* match = oLitEnd - sequence.offset;
Yann Collet5be2dd22015-11-11 13:43:58 +0100707
708 /* check */
709 if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of 8 from oend */
710 if (oMatchEnd > oend) return ERROR(dstSize_tooSmall); /* overwrite beyond dst buffer */
711 if (litEnd > litLimit_8) return ERROR(corruption_detected); /* risk read beyond lit buffer */
712
713 /* copy Literals */
714 ZSTD_wildcopy(op, *litPtr, sequence.litLength); /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */
715 op = oLitEnd;
716 *litPtr = litEnd; /* update for next sequence */
717
718 /* copy Match */
Yann Collet7b51a292016-01-26 15:58:49 +0100719 if (sequence.offset > (size_t)(oLitEnd - base)) {
Yann Collet44287a32015-11-30 23:13:56 +0100720 /* offset beyond prefix */
Yann Collet9f5ab1a2015-12-11 00:27:41 +0100721 if (sequence.offset > (size_t)(oLitEnd - vBase))
722 return ERROR(corruption_detected);
Yann Collet44287a32015-11-30 23:13:56 +0100723 match = dictEnd - (base-match);
Yann Collet7b51a292016-01-26 15:58:49 +0100724 if (match + sequence.matchLength <= dictEnd) {
Yann Collet4bfe4152015-12-06 13:18:37 +0100725 memmove(oLitEnd, match, sequence.matchLength);
Yann Collet44287a32015-11-30 23:13:56 +0100726 return sequenceLength;
727 }
728 /* span extDict & currentPrefixSegment */
729 {
730 size_t length1 = dictEnd - match;
Yann Collet4bfe4152015-12-06 13:18:37 +0100731 memmove(oLitEnd, match, length1);
Yann Collet44287a32015-11-30 23:13:56 +0100732 op = oLitEnd + length1;
733 sequence.matchLength -= length1;
734 match = base;
Yann Colletfb810d62016-01-28 00:18:06 +0100735 } }
Yann Collet0f366c62015-11-12 16:19:30 +0100736
Yann Collet44287a32015-11-30 23:13:56 +0100737 /* match within prefix */
Yann Collet7b51a292016-01-26 15:58:49 +0100738 if (sequence.offset < 8) {
Yann Collet44287a32015-11-30 23:13:56 +0100739 /* close range match, overlap */
740 const int sub2 = dec64table[sequence.offset];
741 op[0] = match[0];
742 op[1] = match[1];
743 op[2] = match[2];
744 op[3] = match[3];
745 match += dec32table[sequence.offset];
746 ZSTD_copy4(op+4, match);
747 match -= sub2;
Yann Colletfb810d62016-01-28 00:18:06 +0100748 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100749 ZSTD_copy8(op, match);
750 }
751 op += 8; match += 8;
Yann Collet5be2dd22015-11-11 13:43:58 +0100752
inikepa4dde252016-03-01 14:14:35 +0100753 if (oMatchEnd > oend-(16-3)) { // 3 = MINMATCH
Yann Collet7b51a292016-01-26 15:58:49 +0100754 if (op < oend_8) {
Yann Collet44287a32015-11-30 23:13:56 +0100755 ZSTD_wildcopy(op, match, oend_8 - op);
756 match += oend_8 - op;
757 op = oend_8;
758 }
Yann Colletfb810d62016-01-28 00:18:06 +0100759 while (op < oMatchEnd)
760 *op++ = *match++;
761 } else {
Yann Collet44287a32015-11-30 23:13:56 +0100762 ZSTD_wildcopy(op, match, sequence.matchLength-8); /* works even if matchLength < 8 */
763 }
764 return sequenceLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100765}
766
Yann Colletb3a2af92015-11-19 17:13:19 +0100767
Yann Collet5be2dd22015-11-11 13:43:58 +0100768static size_t ZSTD_decompressSequences(
Yann Collet5b78d2f2015-11-12 15:36:05 +0100769 ZSTD_DCtx* dctx,
Yann Collet5be2dd22015-11-11 13:43:58 +0100770 void* dst, size_t maxDstSize,
771 const void* seqStart, size_t seqSize)
772{
Yann Collet5be2dd22015-11-11 13:43:58 +0100773 const BYTE* ip = (const BYTE*)seqStart;
774 const BYTE* const iend = ip + seqSize;
775 BYTE* const ostart = (BYTE* const)dst;
776 BYTE* op = ostart;
777 BYTE* const oend = ostart + maxDstSize;
778 size_t errorCode, dumpsLength;
779 const BYTE* litPtr = dctx->litPtr;
780 const BYTE* const litLimit_8 = litPtr + dctx->litBufSize - 8;
781 const BYTE* const litEnd = litPtr + dctx->litSize;
782 int nbSeq;
783 const BYTE* dumps;
784 U32* DTableLL = dctx->LLTable;
785 U32* DTableML = dctx->MLTable;
786 U32* DTableOffb = dctx->OffTable;
Yann Collet417890c2015-12-04 17:16:37 +0100787 const BYTE* const base = (const BYTE*) (dctx->base);
788 const BYTE* const vBase = (const BYTE*) (dctx->vBase);
789 const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
inikep6b3739c2016-02-22 15:53:42 +0100790 const U32 mls = dctx->params.searchLength;
Yann Collet5be2dd22015-11-11 13:43:58 +0100791
792 /* Build Decoding Tables */
793 errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,
794 DTableLL, DTableML, DTableOffb,
Yann Colletfb810d62016-01-28 00:18:06 +0100795 ip, seqSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100796 if (ZSTD_isError(errorCode)) return errorCode;
797 ip += errorCode;
798
799 /* Regen sequences */
Yann Collete93d6ce2016-01-31 00:58:06 +0100800 if (nbSeq) {
Yann Collet5be2dd22015-11-11 13:43:58 +0100801 seq_t sequence;
802 seqState_t seqState;
803
804 memset(&sequence, 0, sizeof(sequence));
Yann Collet61e16ce2016-01-31 02:04:15 +0100805 sequence.offset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100806 seqState.dumps = dumps;
807 seqState.dumpsEnd = dumps + dumpsLength;
Yann Collet61e16ce2016-01-31 02:04:15 +0100808 seqState.prevOffset = REPCODE_STARTVALUE;
Yann Collet5be2dd22015-11-11 13:43:58 +0100809 errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);
810 if (ERR_isError(errorCode)) return ERROR(corruption_detected);
811 FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);
812 FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);
813 FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);
814
Yann Collet7b51a292016-01-26 15:58:49 +0100815 for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; ) {
Yann Colletb3a2af92015-11-19 17:13:19 +0100816 size_t oneSeqSize;
817 nbSeq--;
inikep6b3739c2016-02-22 15:53:42 +0100818 ZSTD_decodeSequence(&sequence, &seqState, mls);
Yann Colletb3a2af92015-11-19 17:13:19 +0100819 oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litLimit_8, base, vBase, dictEnd);
Yann Collet5be2dd22015-11-11 13:43:58 +0100820 if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
821 op += oneSeqSize;
822 }
823
824 /* check if reached exact end */
Yann Collet35f7de52016-01-31 02:51:03 +0100825 if (nbSeq) return ERROR(corruption_detected);
Yann Collete93d6ce2016-01-31 00:58:06 +0100826 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100827
Yann Collete93d6ce2016-01-31 00:58:06 +0100828 /* last literal segment */
829 {
830 size_t lastLLSize = litEnd - litPtr;
831 if (litPtr > litEnd) return ERROR(corruption_detected); /* too many literals already used */
832 if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);
833 memcpy(op, litPtr, lastLLSize);
834 op += lastLLSize;
835 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100836
837 return op-ostart;
838}
839
840
Yann Colletb0125102016-01-09 02:00:10 +0100841static void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)
842{
Yann Collet7b51a292016-01-26 15:58:49 +0100843 if (dst != dctx->previousDstEnd) { /* not contiguous */
Yann Colletb0125102016-01-09 02:00:10 +0100844 dctx->dictEnd = dctx->previousDstEnd;
845 dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
846 dctx->base = dst;
847 dctx->previousDstEnd = dst;
848 }
849}
850
851
852static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100853 void* dst, size_t dstCapacity,
Yann Collet5be2dd22015-11-11 13:43:58 +0100854 const void* src, size_t srcSize)
Yann Colletb010b3b2016-02-03 12:39:34 +0100855{ /* blockType == blockCompressed */
Yann Collet5be2dd22015-11-11 13:43:58 +0100856 const BYTE* ip = (const BYTE*)src;
Yann Colletb010b3b2016-02-03 12:39:34 +0100857 size_t litCSize;
858
859 if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100860
inikepa4dde252016-03-01 14:14:35 +0100861 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBlock_internal searchLength=%d\n", dctx->base, dctx->params.searchLength);
862
Yann Collet5be2dd22015-11-11 13:43:58 +0100863 /* Decode literals sub-block */
Yann Colletb010b3b2016-02-03 12:39:34 +0100864 litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100865 if (ZSTD_isError(litCSize)) return litCSize;
866 ip += litCSize;
867 srcSize -= litCSize;
868
Yann Colletb010b3b2016-02-03 12:39:34 +0100869 return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100870}
871
872
Yann Colletb0125102016-01-09 02:00:10 +0100873size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
Yann Colletb010b3b2016-02-03 12:39:34 +0100874 void* dst, size_t dstCapacity,
Yann Colletb0125102016-01-09 02:00:10 +0100875 const void* src, size_t srcSize)
876{
877 ZSTD_checkContinuity(dctx, dst);
Yann Colletb010b3b2016-02-03 12:39:34 +0100878 return ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
Yann Colletb0125102016-01-09 02:00:10 +0100879}
880
881
Yann Collet7b51a292016-01-26 15:58:49 +0100882/*! ZSTD_decompress_continueDCtx
883* dctx must have been properly initialized */
884static size_t ZSTD_decompress_continueDCtx(ZSTD_DCtx* dctx,
Yann Collet31683c02015-12-18 01:26:48 +0100885 void* dst, size_t maxDstSize,
Yann Collet7b51a292016-01-26 15:58:49 +0100886 const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +0100887{
888 const BYTE* ip = (const BYTE*)src;
889 const BYTE* iend = ip + srcSize;
890 BYTE* const ostart = (BYTE* const)dst;
891 BYTE* op = ostart;
892 BYTE* const oend = ostart + maxDstSize;
893 size_t remainingSize = srcSize;
Yann Collet5be2dd22015-11-11 13:43:58 +0100894 blockProperties_t blockProperties;
895
896 /* Frame Header */
Yann Collet88fcd292015-11-25 14:42:45 +0100897 {
898 size_t frameHeaderSize;
899 if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
Yann Collet5be2dd22015-11-11 13:43:58 +0100900#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT==1)
Yann Collet88fcd292015-11-25 14:42:45 +0100901 {
902 const U32 magicNumber = MEM_readLE32(src);
903 if (ZSTD_isLegacy(magicNumber))
904 return ZSTD_decompressLegacy(dst, maxDstSize, src, srcSize, magicNumber);
905 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100906#endif
Yann Collet37422192016-01-25 16:54:05 +0100907 frameHeaderSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min);
Yann Collet88fcd292015-11-25 14:42:45 +0100908 if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
909 if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);
910 ip += frameHeaderSize; remainingSize -= frameHeaderSize;
Yann Collet37422192016-01-25 16:54:05 +0100911 frameHeaderSize = ZSTD_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);
Yann Collet88fcd292015-11-25 14:42:45 +0100912 if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
913 }
Yann Collet5be2dd22015-11-11 13:43:58 +0100914
915 /* Loop on each block */
916 while (1)
917 {
918 size_t decodedSize=0;
919 size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);
920 if (ZSTD_isError(cBlockSize)) return cBlockSize;
921
922 ip += ZSTD_blockHeaderSize;
923 remainingSize -= ZSTD_blockHeaderSize;
924 if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);
925
926 switch(blockProperties.blockType)
927 {
928 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +0100929 decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100930 break;
931 case bt_raw :
Yann Collet0f366c62015-11-12 16:19:30 +0100932 decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);
Yann Collet5be2dd22015-11-11 13:43:58 +0100933 break;
934 case bt_rle :
935 return ERROR(GENERIC); /* not yet supported */
936 break;
937 case bt_end :
938 /* end of frame */
939 if (remainingSize) return ERROR(srcSize_wrong);
940 break;
941 default:
942 return ERROR(GENERIC); /* impossible */
943 }
944 if (cBlockSize == 0) break; /* bt_end */
945
946 if (ZSTD_isError(decodedSize)) return decodedSize;
947 op += decodedSize;
948 ip += cBlockSize;
949 remainingSize -= cBlockSize;
950 }
951
952 return op-ostart;
953}
954
Yann Collet31683c02015-12-18 01:26:48 +0100955
Yann Collet7b51a292016-01-26 15:58:49 +0100956size_t ZSTD_decompress_usingPreparedDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* refDCtx,
957 void* dst, size_t maxDstSize,
958 const void* src, size_t srcSize)
959{
960 ZSTD_copyDCtx(dctx, refDCtx);
961 ZSTD_checkContinuity(dctx, dst);
962 return ZSTD_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);
963}
964
965
966size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
967 void* dst, size_t maxDstSize,
968 const void* src, size_t srcSize,
969 const void* dict, size_t dictSize)
970{
971 ZSTD_decompressBegin_usingDict(dctx, dict, dictSize);
inikepa4dde252016-03-01 14:14:35 +0100972 ZSTD_LOG_BLOCK("%p: ZSTD_decompressBegin_usingDict searchLength=%d\n", dctx->base, dctx->params.searchLength);
Yann Collet7b51a292016-01-26 15:58:49 +0100973 ZSTD_checkContinuity(dctx, dst);
974 return ZSTD_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);
975}
976
977
Yann Collet31683c02015-12-18 01:26:48 +0100978size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
979{
980 return ZSTD_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);
981}
982
Yann Collet5be2dd22015-11-11 13:43:58 +0100983size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)
984{
Yann Collet3a3b72f2016-01-11 12:56:11 +0100985#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)
986 size_t regenSize;
987 ZSTD_DCtx* dctx = ZSTD_createDCtx();
988 if (dctx==NULL) return ERROR(memory_allocation);
989 regenSize = ZSTD_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);
990 ZSTD_freeDCtx(dctx);
991 return regenSize;
992#else
Yann Collet31683c02015-12-18 01:26:48 +0100993 ZSTD_DCtx dctx;
994 return ZSTD_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);
Yann Colleta768a302016-01-21 16:04:35 +0100995#endif
Yann Collet5be2dd22015-11-11 13:43:58 +0100996}
997
998
999/* ******************************
1000* Streaming Decompression API
1001********************************/
Yann Collet5be2dd22015-11-11 13:43:58 +01001002size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)
1003{
1004 return dctx->expected;
1005}
1006
Yann Collet37422192016-01-25 16:54:05 +01001007size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)
Yann Collet5be2dd22015-11-11 13:43:58 +01001008{
1009 /* Sanity check */
Yann Collet37422192016-01-25 16:54:05 +01001010 if (srcSize != dctx->expected) return ERROR(srcSize_wrong);
1011 ZSTD_checkContinuity(dctx, dst);
Yann Collet5be2dd22015-11-11 13:43:58 +01001012
Yann Collet88fcd292015-11-25 14:42:45 +01001013 /* Decompress : frame header; part 1 */
Yann Collet37422192016-01-25 16:54:05 +01001014 switch (dctx->stage)
Yann Collet5be2dd22015-11-11 13:43:58 +01001015 {
Yann Collet88fcd292015-11-25 14:42:45 +01001016 case ZSTDds_getFrameHeaderSize :
Yann Collet5be2dd22015-11-11 13:43:58 +01001017 {
Yann Collet88fcd292015-11-25 14:42:45 +01001018 /* get frame header size */
1019 if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong); /* impossible */
Yann Collet37422192016-01-25 16:54:05 +01001020 dctx->headerSize = ZSTD_decodeFrameHeader_Part1(dctx, src, ZSTD_frameHeaderSize_min);
1021 if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
1022 memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_min);
Yann Collet7b51a292016-01-26 15:58:49 +01001023 if (dctx->headerSize > ZSTD_frameHeaderSize_min) {
Yann Collet37422192016-01-25 16:54:05 +01001024 dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_min;
1025 dctx->stage = ZSTDds_decodeFrameHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001026 return 0;
1027 }
Yann Collet37422192016-01-25 16:54:05 +01001028 dctx->expected = 0; /* not necessary to copy more */
Yann Collet5be2dd22015-11-11 13:43:58 +01001029 }
Yann Collet88fcd292015-11-25 14:42:45 +01001030 case ZSTDds_decodeFrameHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001031 {
Yann Collet88fcd292015-11-25 14:42:45 +01001032 /* get frame header */
1033 size_t result;
Yann Collet37422192016-01-25 16:54:05 +01001034 memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_min, src, dctx->expected);
1035 result = ZSTD_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001036 if (ZSTD_isError(result)) return result;
Yann Collet37422192016-01-25 16:54:05 +01001037 dctx->expected = ZSTD_blockHeaderSize;
1038 dctx->stage = ZSTDds_decodeBlockHeader;
Yann Collet88fcd292015-11-25 14:42:45 +01001039 return 0;
Yann Collet5be2dd22015-11-11 13:43:58 +01001040 }
Yann Collet88fcd292015-11-25 14:42:45 +01001041 case ZSTDds_decodeBlockHeader:
Yann Collet5be2dd22015-11-11 13:43:58 +01001042 {
Yann Collet88fcd292015-11-25 14:42:45 +01001043 /* Decode block header */
1044 blockProperties_t bp;
1045 size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
1046 if (ZSTD_isError(blockSize)) return blockSize;
Yann Collet7b51a292016-01-26 15:58:49 +01001047 if (bp.blockType == bt_end) {
Yann Collet37422192016-01-25 16:54:05 +01001048 dctx->expected = 0;
1049 dctx->stage = ZSTDds_getFrameHeaderSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001050 }
Yann Collet7b51a292016-01-26 15:58:49 +01001051 else {
Yann Collet37422192016-01-25 16:54:05 +01001052 dctx->expected = blockSize;
1053 dctx->bType = bp.blockType;
1054 dctx->stage = ZSTDds_decompressBlock;
Yann Collet88fcd292015-11-25 14:42:45 +01001055 }
Yann Collet88fcd292015-11-25 14:42:45 +01001056 return 0;
1057 }
Yann Collet417890c2015-12-04 17:16:37 +01001058 case ZSTDds_decompressBlock:
Yann Collet88fcd292015-11-25 14:42:45 +01001059 {
1060 /* Decompress : block content */
1061 size_t rSize;
Yann Collet37422192016-01-25 16:54:05 +01001062 switch(dctx->bType)
Yann Collet88fcd292015-11-25 14:42:45 +01001063 {
1064 case bt_compressed:
Yann Collet37422192016-01-25 16:54:05 +01001065 rSize = ZSTD_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);
Yann Collet88fcd292015-11-25 14:42:45 +01001066 break;
1067 case bt_raw :
1068 rSize = ZSTD_copyRawBlock(dst, maxDstSize, src, srcSize);
1069 break;
1070 case bt_rle :
1071 return ERROR(GENERIC); /* not yet handled */
1072 break;
1073 case bt_end : /* should never happen (filtered at phase 1) */
1074 rSize = 0;
1075 break;
1076 default:
Yann Collet7b51a292016-01-26 15:58:49 +01001077 return ERROR(GENERIC); /* impossible */
Yann Collet88fcd292015-11-25 14:42:45 +01001078 }
Yann Collet37422192016-01-25 16:54:05 +01001079 dctx->stage = ZSTDds_decodeBlockHeader;
1080 dctx->expected = ZSTD_blockHeaderSize;
1081 dctx->previousDstEnd = (char*)dst + rSize;
Yann Collet88fcd292015-11-25 14:42:45 +01001082 return rSize;
1083 }
1084 default:
1085 return ERROR(GENERIC); /* impossible */
1086 }
Yann Collet5be2dd22015-11-11 13:43:58 +01001087}
1088
1089
Yann Colletb923f652016-01-26 03:14:20 +01001090static void ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Collet417890c2015-12-04 17:16:37 +01001091{
Yann Collet37422192016-01-25 16:54:05 +01001092 dctx->dictEnd = dctx->previousDstEnd;
1093 dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));
1094 dctx->base = dict;
1095 dctx->previousDstEnd = (const char*)dict + dictSize;
Yann Collet417890c2015-12-04 17:16:37 +01001096}
Yann Colletb923f652016-01-26 03:14:20 +01001097
Yann Colletb923f652016-01-26 03:14:20 +01001098static size_t ZSTD_loadEntropy(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1099{
Yann Colletfb810d62016-01-28 00:18:06 +01001100 size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;
1101 short offcodeNCount[MaxOff+1];
1102 U32 offcodeMaxValue=MaxOff, offcodeLog=OffFSELog;
1103 short matchlengthNCount[MaxML+1];
1104 unsigned matchlengthMaxValue = MaxML, matchlengthLog = MLFSELog;
1105 short litlengthNCount[MaxLL+1];
1106 unsigned litlengthMaxValue = MaxLL, litlengthLog = LLFSELog;
1107
1108 hSize = HUF_readDTableX4(dctx->hufTableX4, dict, dictSize);
Yann Colletb923f652016-01-26 03:14:20 +01001109 if (HUF_isError(hSize)) return ERROR(dictionary_corrupted);
Yann Colletfb810d62016-01-28 00:18:06 +01001110 dict = (const char*)dict + hSize;
1111 dictSize -= hSize;
1112
1113 offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);
1114 if (FSE_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);
1115 errorCode = FSE_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);
1116 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1117 dict = (const char*)dict + offcodeHeaderSize;
1118 dictSize -= offcodeHeaderSize;
1119
1120 matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);
1121 if (FSE_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);
1122 errorCode = FSE_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);
1123 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1124 dict = (const char*)dict + matchlengthHeaderSize;
1125 dictSize -= matchlengthHeaderSize;
1126
1127 litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);
1128 if (FSE_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);
1129 errorCode = FSE_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);
1130 if (FSE_isError(errorCode)) return ERROR(dictionary_corrupted);
1131
1132 dctx->flagStaticTables = 1;
1133 return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;
Yann Colletb923f652016-01-26 03:14:20 +01001134}
1135
Yann Collet7b51a292016-01-26 15:58:49 +01001136static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
Yann Colletb923f652016-01-26 03:14:20 +01001137{
1138 size_t eSize;
1139 U32 magic = MEM_readLE32(dict);
1140 if (magic != ZSTD_DICT_MAGIC) {
1141 /* pure content mode */
1142 ZSTD_refDictContent(dctx, dict, dictSize);
1143 return 0;
1144 }
1145 /* load entropy tables */
1146 dict = (const char*)dict + 4;
1147 dictSize -= 4;
1148 eSize = ZSTD_loadEntropy(dctx, dict, dictSize);
1149 if (ZSTD_isError(eSize)) return ERROR(dictionary_corrupted);
1150
1151 /* reference dictionary content */
1152 dict = (const char*)dict + eSize;
1153 dictSize -= eSize;
1154 ZSTD_refDictContent(dctx, dict, dictSize);
1155
1156 return 0;
1157}
1158
Yann Collet7b51a292016-01-26 15:58:49 +01001159
1160size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
1161{
1162 size_t errorCode;
1163 errorCode = ZSTD_decompressBegin(dctx);
1164 if (ZSTD_isError(errorCode)) return errorCode;
1165
1166 if (dict && dictSize) {
1167 errorCode = ZSTD_decompress_insertDictionary(dctx, dict, dictSize);
1168 if (ZSTD_isError(errorCode)) return ERROR(dictionary_corrupted);
1169 }
1170
1171 return 0;
1172}
1173