blob: b3be4e5b443b618a704b9b8ec6e1106f530a4d10 [file] [log] [blame]
Julius Wernerbf273912015-06-30 10:30:30 -07001/*
2 LZ4 - Fast LZ compression algorithm
3 Copyright (C) 2011-2015, Yann Collet.
4
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
11 * Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 * Redistributions in binary form must reproduce the above
14 copyright notice, this list of conditions and the following disclaimer
15 in the documentation and/or other materials provided with the
16 distribution.
17
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 You can contact the author at :
31 - LZ4 source repository : https://github.com/Cyan4973/lz4
32 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
33*/
34
35
36/**************************************
37* Reading and writing into memory
38**************************************/
39
Julius Werner09f29212015-09-29 13:51:35 -070040/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */
Julius Wernerbf273912015-06-30 10:30:30 -070041static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
42{
43 BYTE* d = (BYTE*)dstPtr;
44 const BYTE* s = (const BYTE*)srcPtr;
Julius Werner09f29212015-09-29 13:51:35 -070045 BYTE* const e = (BYTE*)dstEnd;
46
47#if 0
48 const size_t l2 = 8 - (((size_t)d) & (sizeof(void*)-1));
49 LZ4_copy8(d,s); if (d>e-9) return;
50 d+=l2; s+=l2;
51#endif /* join to align */
52
Julius Wernerbf273912015-06-30 10:30:30 -070053 do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
54}
55
56
57/**************************************
58* Common Constants
59**************************************/
60#define MINMATCH 4
61
Julius Werner09f29212015-09-29 13:51:35 -070062#define WILDCOPYLENGTH 8
Julius Wernerbf273912015-06-30 10:30:30 -070063#define LASTLITERALS 5
Julius Werner09f29212015-09-29 13:51:35 -070064#define MFLIMIT (WILDCOPYLENGTH+MINMATCH)
Julius Wernerbf273912015-06-30 10:30:30 -070065static const int LZ4_minLength = (MFLIMIT+1);
66
67#define KB *(1 <<10)
68#define MB *(1 <<20)
69#define GB *(1U<<30)
70
71#define MAXD_LOG 16
72#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
73
74#define ML_BITS 4
75#define ML_MASK ((1U<<ML_BITS)-1)
76#define RUN_BITS (8-ML_BITS)
77#define RUN_MASK ((1U<<RUN_BITS)-1)
78
79
80/**************************************
81* Local Structures and types
82**************************************/
83typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
84typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
85typedef enum { full = 0, partial = 1 } earlyEnd_directive;
86
87
88
89/*******************************
90* Decompression functions
91*******************************/
92/*
93 * This generic decompression function cover all use cases.
94 * It shall be instantiated several times, using different sets of directives
95 * Note that it is essential this generic function is really inlined,
96 * in order to remove useless branches during compilation optimization.
97 */
98FORCE_INLINE int LZ4_decompress_generic(
99 const char* const source,
100 char* const dest,
101 int inputSize,
102 int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */
103
104 int endOnInput, /* endOnOutputSize, endOnInputSize */
105 int partialDecoding, /* full, partial */
106 int targetOutputSize, /* only used if partialDecoding==partial */
107 int dict, /* noDict, withPrefix64k, usingExtDict */
108 const BYTE* const lowPrefix, /* == dest if dict == noDict */
109 const BYTE* const dictStart, /* only if dict==usingExtDict */
110 const size_t dictSize /* note : = 0 if noDict */
111 )
112{
113 /* Local Variables */
114 const BYTE* ip = (const BYTE*) source;
115 const BYTE* const iend = ip + inputSize;
116
117 BYTE* op = (BYTE*) dest;
118 BYTE* const oend = op + outputSize;
119 BYTE* cpy;
120 BYTE* oexit = op + targetOutputSize;
121 const BYTE* const lowLimit = lowPrefix - dictSize;
122
123 const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
Julius Werner09f29212015-09-29 13:51:35 -0700124 const unsigned dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};
125 const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};
Julius Wernerbf273912015-06-30 10:30:30 -0700126
127 const int safeDecode = (endOnInput==endOnInputSize);
128 const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB)));
Julius Werner09f29212015-09-29 13:51:35 -0700129 const int inPlaceDecode = ((ip >= op) && (ip < oend));
Julius Wernerbf273912015-06-30 10:30:30 -0700130
131
132 /* Special cases */
133 if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */
134 if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */
135 if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);
136
137
138 /* Main Loop */
139 while (1)
140 {
141 unsigned token;
142 size_t length;
143 const BYTE* match;
Julius Werner09f29212015-09-29 13:51:35 -0700144 size_t offset;
145
146 if (unlikely((inPlaceDecode) && (op + WILDCOPYLENGTH > ip))) goto _output_error; /* output stream ran over input stream */
Julius Wernerbf273912015-06-30 10:30:30 -0700147
148 /* get literal length */
149 token = *ip++;
150 if ((length=(token>>ML_BITS)) == RUN_MASK)
151 {
152 unsigned s;
153 do
154 {
155 s = *ip++;
156 length += s;
157 }
Julius Werner09f29212015-09-29 13:51:35 -0700158 while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) && (s==255) );
Julius Wernerbf273912015-06-30 10:30:30 -0700159 if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* overflow detection */
160 if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* overflow detection */
161 }
162
163 /* copy literals */
164 cpy = op+length;
165 if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) )
Julius Werner09f29212015-09-29 13:51:35 -0700166 || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)))
Julius Wernerbf273912015-06-30 10:30:30 -0700167 {
168 if (partialDecoding)
169 {
170 if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */
171 if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */
172 }
173 else
174 {
175 if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */
176 if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */
177 }
Julius Werner09f29212015-09-29 13:51:35 -0700178 memmove(op, ip, length);
Julius Wernerbf273912015-06-30 10:30:30 -0700179 ip += length;
180 op += length;
181 break; /* Necessarily EOF, due to parsing restrictions */
182 }
183 LZ4_wildCopy(op, ip, cpy);
184 ip += length; op = cpy;
185
186 /* get offset */
Julius Werner09f29212015-09-29 13:51:35 -0700187 offset = LZ4_readLE16(ip); ip+=2;
188 match = op - offset;
189 if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside buffers */
Julius Wernerbf273912015-06-30 10:30:30 -0700190
191 /* get matchlength */
192 length = token & ML_MASK;
193 if (length == ML_MASK)
194 {
195 unsigned s;
196 do
197 {
198 if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;
199 s = *ip++;
200 length += s;
201 } while (s==255);
202 if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* overflow detection */
203 }
204 length += MINMATCH;
205
206 /* check external dictionary */
207 if ((dict==usingExtDict) && (match < lowPrefix))
208 {
209 if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */
210
211 if (length <= (size_t)(lowPrefix-match))
212 {
213 /* match can be copied as a single segment from external dictionary */
214 match = dictEnd - (lowPrefix-match);
215 memmove(op, match, length); op += length;
216 }
217 else
218 {
Julius Werner09f29212015-09-29 13:51:35 -0700219 /* match encompass external dictionary and current block */
Julius Wernerbf273912015-06-30 10:30:30 -0700220 size_t copySize = (size_t)(lowPrefix-match);
221 memcpy(op, dictEnd - copySize, copySize);
222 op += copySize;
223 copySize = length - copySize;
Julius Werner09f29212015-09-29 13:51:35 -0700224 if (copySize > (size_t)(op-lowPrefix)) /* overlap copy */
Julius Wernerbf273912015-06-30 10:30:30 -0700225 {
226 BYTE* const endOfMatch = op + copySize;
227 const BYTE* copyFrom = lowPrefix;
228 while (op < endOfMatch) *op++ = *copyFrom++;
229 }
230 else
231 {
232 memcpy(op, lowPrefix, copySize);
233 op += copySize;
234 }
235 }
236 continue;
237 }
238
Julius Werner09f29212015-09-29 13:51:35 -0700239 /* copy match within block */
Julius Wernerbf273912015-06-30 10:30:30 -0700240 cpy = op + length;
Julius Werner09f29212015-09-29 13:51:35 -0700241 if (unlikely(offset<8))
Julius Wernerbf273912015-06-30 10:30:30 -0700242 {
Julius Werner09f29212015-09-29 13:51:35 -0700243 const int dec64 = dec64table[offset];
Julius Wernerbf273912015-06-30 10:30:30 -0700244 op[0] = match[0];
245 op[1] = match[1];
246 op[2] = match[2];
247 op[3] = match[3];
Julius Werner09f29212015-09-29 13:51:35 -0700248 match += dec32table[offset];
249 memcpy(op+4, match, 4);
250 match -= dec64;
251 } else { LZ4_copy8(op, match); match+=8; }
252 op += 8;
Julius Wernerbf273912015-06-30 10:30:30 -0700253
254 if (unlikely(cpy>oend-12))
255 {
Julius Werner09f29212015-09-29 13:51:35 -0700256 BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);
257 if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */
258 if (op < oCopyLimit)
Julius Wernerbf273912015-06-30 10:30:30 -0700259 {
Julius Werner09f29212015-09-29 13:51:35 -0700260 LZ4_wildCopy(op, match, oCopyLimit);
261 match += oCopyLimit - op;
262 op = oCopyLimit;
Julius Wernerbf273912015-06-30 10:30:30 -0700263 }
264 while (op<cpy) *op++ = *match++;
265 }
266 else
267 LZ4_wildCopy(op, match, cpy);
268 op=cpy; /* correction */
269 }
270
271 /* end of decoding */
272 if (endOnInput)
273 return (int) (((char*)op)-dest); /* Nb of output bytes decoded */
274 else
275 return (int) (((const char*)ip)-source); /* Nb of input bytes read */
276
277 /* Overflow error detected */
278_output_error:
279 return (int) (-(((const char*)ip)-source))-1;
280}