blob: 2a9f36aa21e56872c7c30276b7f67a49c4d50e53 [file] [log] [blame]
Yann Collet4ded9e52016-08-30 10:04:33 -07001/**
2 * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
8 */
Yann Colletaa074052015-10-30 11:21:50 +01009
Yann Colletaa074052015-10-30 11:21:50 +010010#ifndef ZSTD_LEGACY_H
11#define ZSTD_LEGACY_H
12
13#if defined (__cplusplus)
14extern "C" {
15#endif
16
17/* *************************************
18* Includes
19***************************************/
Yann Colletffec7402016-01-21 15:50:11 +010020#include "mem.h" /* MEM_STATIC */
21#include "error_private.h" /* ERROR */
Yann Collet4bf317d2016-08-28 07:43:34 -070022#include "zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer */
Yann Colletaa074052015-10-30 11:21:50 +010023#include "zstd_v01.h"
24#include "zstd_v02.h"
Yann Collet29a2c832015-11-26 16:02:04 +010025#include "zstd_v03.h"
Yann Collet464fa992016-02-03 01:09:46 +010026#include "zstd_v04.h"
Yann Collet029267a2016-04-09 09:42:27 +020027#include "zstd_v05.h"
inikepbf853d52016-06-09 17:59:18 +020028#include "zstd_v06.h"
inikepfca90f82016-07-25 17:49:08 +020029#include "zstd_v07.h"
Yann Colletaa074052015-10-30 11:21:50 +010030
Yann Collet18dedec2016-05-06 16:43:23 +020031
32/** ZSTD_isLegacy() :
33 @return : > 0 if supported by legacy decoder. 0 otherwise.
34 return value is the version.
35*/
Yann Collet19c27d22016-07-07 14:40:13 +020036MEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize)
Yann Colletaa074052015-10-30 11:21:50 +010037{
Yann Collet19c27d22016-07-07 14:40:13 +020038 U32 magicNumberLE;
39 if (srcSize<4) return 0;
40 magicNumberLE = MEM_readLE32(src);
inikepbf853d52016-06-09 17:59:18 +020041 switch(magicNumberLE)
42 {
43 case ZSTDv01_magicNumberLE:return 1;
44 case ZSTDv02_magicNumber : return 2;
45 case ZSTDv03_magicNumber : return 3;
46 case ZSTDv04_magicNumber : return 4;
47 case ZSTDv05_MAGICNUMBER : return 5;
48 case ZSTDv06_MAGICNUMBER : return 6;
inikepfca90f82016-07-25 17:49:08 +020049 case ZSTDv07_MAGICNUMBER : return 7;
inikepbf853d52016-06-09 17:59:18 +020050 default : return 0;
51 }
Yann Colletaa074052015-10-30 11:21:50 +010052}
53
54
Yann Colletf323bf72016-07-07 13:14:21 +020055MEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, size_t srcSize)
56{
Yann Collet4bf317d2016-08-28 07:43:34 -070057 U32 const version = ZSTD_isLegacy(src, srcSize);
58 if (version < 5) return 0; /* no decompressed size in frame header, or not a legacy format */
59 if (version==5) {
60 ZSTDv05_parameters fParams;
61 size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize);
62 if (frResult != 0) return 0;
63 return fParams.srcSize;
Yann Colletf323bf72016-07-07 13:14:21 +020064 }
Yann Collet4bf317d2016-08-28 07:43:34 -070065 if (version==6) {
66 ZSTDv06_frameParams fParams;
67 size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize);
68 if (frResult != 0) return 0;
69 return fParams.frameContentSize;
70 }
71 if (version==7) {
72 ZSTDv07_frameParams fParams;
73 size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize);
74 if (frResult != 0) return 0;
75 return fParams.frameContentSize;
76 }
77 return 0; /* should not be possible */
Yann Colletf323bf72016-07-07 13:14:21 +020078}
79
Yann Collet4bf317d2016-08-28 07:43:34 -070080
Yann Colletaa074052015-10-30 11:21:50 +010081MEM_STATIC size_t ZSTD_decompressLegacy(
Yann Collet029267a2016-04-09 09:42:27 +020082 void* dst, size_t dstCapacity,
Yann Colletaa074052015-10-30 11:21:50 +010083 const void* src, size_t compressedSize,
Yann Collet19c27d22016-07-07 14:40:13 +020084 const void* dict,size_t dictSize)
Yann Colletaa074052015-10-30 11:21:50 +010085{
Yann Collet19c27d22016-07-07 14:40:13 +020086 U32 const version = ZSTD_isLegacy(src, compressedSize);
87 switch(version)
inikepbf853d52016-06-09 17:59:18 +020088 {
Yann Collet19c27d22016-07-07 14:40:13 +020089 case 1 :
inikepbf853d52016-06-09 17:59:18 +020090 return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize);
Yann Collet19c27d22016-07-07 14:40:13 +020091 case 2 :
inikepbf853d52016-06-09 17:59:18 +020092 return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize);
Yann Collet19c27d22016-07-07 14:40:13 +020093 case 3 :
inikepbf853d52016-06-09 17:59:18 +020094 return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize);
Yann Collet19c27d22016-07-07 14:40:13 +020095 case 4 :
inikepbf853d52016-06-09 17:59:18 +020096 return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize);
Yann Collet19c27d22016-07-07 14:40:13 +020097 case 5 :
Yann Collet289bbd52016-06-11 00:23:43 +020098 { size_t result;
99 ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx();
inikepbf853d52016-06-09 17:59:18 +0200100 if (zd==NULL) return ERROR(memory_allocation);
101 result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);
102 ZSTDv05_freeDCtx(zd);
103 return result;
104 }
Yann Collet19c27d22016-07-07 14:40:13 +0200105 case 6 :
Yann Collet289bbd52016-06-11 00:23:43 +0200106 { size_t result;
107 ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx();
inikepbf853d52016-06-09 17:59:18 +0200108 if (zd==NULL) return ERROR(memory_allocation);
109 result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);
110 ZSTDv06_freeDCtx(zd);
111 return result;
112 }
inikepfca90f82016-07-25 17:49:08 +0200113 case 7 :
114 { size_t result;
115 ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx();
116 if (zd==NULL) return ERROR(memory_allocation);
117 result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);
118 ZSTDv07_freeDCtx(zd);
119 return result;
120 }
inikepbf853d52016-06-09 17:59:18 +0200121 default :
122 return ERROR(prefix_unknown);
123 }
Yann Colletaa074052015-10-30 11:21:50 +0100124}
125
126
Yann Collet4bf317d2016-08-28 07:43:34 -0700127MEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)
128{
129 switch(version)
130 {
131 default :
132 case 1 :
133 case 2 :
134 case 3 :
135 return ERROR(version_unsupported);
136 case 4 : return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx*)legacyContext);
137 case 5 : return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx*)legacyContext);
138 case 6 : return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx*)legacyContext);
139 case 7 : return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx*)legacyContext);
140 }
141}
142
143
Yann Collet767d8f62016-08-28 08:19:47 -0700144MEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion,
145 const void* dict, size_t dictSize)
Yann Collet4bf317d2016-08-28 07:43:34 -0700146{
Yann Collet767d8f62016-08-28 08:19:47 -0700147 if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion);
148 switch(newVersion)
Yann Collet4bf317d2016-08-28 07:43:34 -0700149 {
150 default :
151 case 1 :
152 case 2 :
153 case 3 :
Yann Collet767d8f62016-08-28 08:19:47 -0700154 return 0;
Yann Collet4bf317d2016-08-28 07:43:34 -0700155 case 4 :
156 {
Yann Collet767d8f62016-08-28 08:19:47 -0700157 ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext;
158 if (dctx==NULL) return ERROR(memory_allocation);
Yann Collet4bf317d2016-08-28 07:43:34 -0700159 ZBUFFv04_decompressInit(dctx);
160 ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize);
Yann Collet767d8f62016-08-28 08:19:47 -0700161 *legacyContext = dctx;
162 return 0;
Yann Collet4bf317d2016-08-28 07:43:34 -0700163 }
164 case 5 :
165 {
Yann Collet767d8f62016-08-28 08:19:47 -0700166 ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext;
167 if (dctx==NULL) return ERROR(memory_allocation);
Yann Collet4bf317d2016-08-28 07:43:34 -0700168 ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize);
Yann Collet767d8f62016-08-28 08:19:47 -0700169 *legacyContext = dctx;
170 return 0;
Yann Collet4bf317d2016-08-28 07:43:34 -0700171 }
172 case 6 :
173 {
Yann Collet767d8f62016-08-28 08:19:47 -0700174 ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext;
175 if (dctx==NULL) return ERROR(memory_allocation);
Yann Collet4bf317d2016-08-28 07:43:34 -0700176 ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize);
Yann Collet767d8f62016-08-28 08:19:47 -0700177 *legacyContext = dctx;
178 return 0;
Yann Collet4bf317d2016-08-28 07:43:34 -0700179 }
180 case 7 :
181 {
Yann Collet767d8f62016-08-28 08:19:47 -0700182 ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext;
183 if (dctx==NULL) return ERROR(memory_allocation);
Yann Collet4bf317d2016-08-28 07:43:34 -0700184 ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize);
Yann Collet767d8f62016-08-28 08:19:47 -0700185 *legacyContext = dctx;
186 return 0;
Yann Collet4bf317d2016-08-28 07:43:34 -0700187 }
188 }
189}
190
191
192
Yann Collet767d8f62016-08-28 08:19:47 -0700193MEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,
194 ZSTD_outBuffer* output, ZSTD_inBuffer* input)
Yann Collet4bf317d2016-08-28 07:43:34 -0700195{
Yann Collet4bf317d2016-08-28 07:43:34 -0700196 switch(version)
197 {
198 default :
199 case 1 :
200 case 2 :
201 case 3 :
202 return ERROR(version_unsupported);
203 case 4 :
204 {
Yann Collet767d8f62016-08-28 08:19:47 -0700205 ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext;
Yann Collet4bf317d2016-08-28 07:43:34 -0700206 const void* src = (const char*)input->src + input->pos;
207 size_t readSize = input->size - input->pos;
208 void* dst = (char*)output->dst + output->pos;
209 size_t decodedSize = output->size - output->pos;
210 size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
211 output->pos += decodedSize;
212 input->pos += readSize;
213 return hintSize;
214 }
215 case 5 :
216 {
Yann Collet767d8f62016-08-28 08:19:47 -0700217 ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext;
Yann Collet4bf317d2016-08-28 07:43:34 -0700218 const void* src = (const char*)input->src + input->pos;
219 size_t readSize = input->size - input->pos;
220 void* dst = (char*)output->dst + output->pos;
221 size_t decodedSize = output->size - output->pos;
222 size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
223 output->pos += decodedSize;
224 input->pos += readSize;
225 return hintSize;
226 }
227 case 6 :
228 {
Yann Collet767d8f62016-08-28 08:19:47 -0700229 ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext;
Yann Collet4bf317d2016-08-28 07:43:34 -0700230 const void* src = (const char*)input->src + input->pos;
231 size_t readSize = input->size - input->pos;
232 void* dst = (char*)output->dst + output->pos;
233 size_t decodedSize = output->size - output->pos;
234 size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
235 output->pos += decodedSize;
236 input->pos += readSize;
237 return hintSize;
238 }
239 case 7 :
240 {
Yann Collet767d8f62016-08-28 08:19:47 -0700241 ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext;
Yann Collet4bf317d2016-08-28 07:43:34 -0700242 const void* src = (const char*)input->src + input->pos;
243 size_t readSize = input->size - input->pos;
244 void* dst = (char*)output->dst + output->pos;
245 size_t decodedSize = output->size - output->pos;
246 size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize);
247 output->pos += decodedSize;
248 input->pos += readSize;
249 return hintSize;
250 }
251 }
252}
253
Yann Colletaa074052015-10-30 11:21:50 +0100254
255#if defined (__cplusplus)
256}
257#endif
258
259#endif /* ZSTD_LEGACY_H */