git subrepo pull (merge) --force deps/libchdr
[pcsx_rearmed.git] / deps / libchdr / deps / zstd-1.5.5 / zlibWrapper / zstd_zlibwrapper.c
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under both the BSD-style license (found in the
6  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7  * in the COPYING file in the root directory of this source tree).
8  * You may select, at your option, one of the above-listed licenses.
9  */
10
11
12 /* ===   Tuning parameters   === */
13 #ifndef ZWRAP_USE_ZSTD
14     #define ZWRAP_USE_ZSTD 0
15 #endif
16
17
18 /* ===   Dependencies   === */
19 #include <stdlib.h>
20 #include <stdio.h>                 /* vsprintf */
21 #include <stdarg.h>                /* va_list, for z_gzprintf */
22 #include <string.h>
23 #define NO_DUMMY_DECL
24 #define ZLIB_CONST
25 #include <zlib.h>                  /* without #define Z_PREFIX */
26 #include "zstd_zlibwrapper.h"
27 #define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_isFrame, ZSTD_MAGICNUMBER, ZSTD_customMem */
28 #include "zstd.h"
29
30
31 /* ===   Constants   === */
32 #define Z_INFLATE_SYNC              8
33 #define ZLIB_HEADERSIZE             4
34 #define ZSTD_HEADERSIZE             ZSTD_FRAMEHEADERSIZE_MIN(ZSTD_f_zstd1)
35 #define ZWRAP_DEFAULT_CLEVEL        3   /* Z_DEFAULT_COMPRESSION is translated to ZWRAP_DEFAULT_CLEVEL for zstd */
36
37
38 /* ===   Debug   === */
39 #define LOG_WRAPPERC(...)  /* fprintf(stderr, __VA_ARGS__) */
40 #define LOG_WRAPPERD(...)  /* fprintf(stderr, __VA_ARGS__) */
41
42 #define FINISH_WITH_GZ_ERR(msg) { (void)msg; return Z_STREAM_ERROR; }
43 #define FINISH_WITH_NULL_ERR(msg) { (void)msg; return NULL; }
44
45 /* ===   Utility   === */
46
47 #define MIN(x,y) ((x) < (y) ? (x) : (y))
48
49 static unsigned ZWRAP_isLittleEndian(void)
50 {
51     const union { unsigned u; char c[4]; } one = { 1 };   /* don't use static : performance detrimental  */
52     return one.c[0];
53 }
54
55 #ifndef __has_builtin
56 # define __has_builtin(x) 0
57 #endif
58
59 static unsigned ZWRAP_swap32(unsigned in)
60 {
61 #if defined(_MSC_VER)     /* Visual Studio */
62     return _byteswap_ulong(in);
63 #elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \
64   || (defined(__clang__) && __has_builtin(__builtin_bswap32))
65     return __builtin_bswap32(in);
66 #else
67     return  ((in << 24) & 0xff000000 ) |
68             ((in <<  8) & 0x00ff0000 ) |
69             ((in >>  8) & 0x0000ff00 ) |
70             ((in >> 24) & 0x000000ff );
71 #endif
72 }
73
74 static unsigned ZWRAP_readLE32(const void* ptr)
75 {
76     unsigned value;
77     memcpy(&value, ptr, sizeof(value));
78     if (ZWRAP_isLittleEndian())
79         return value;
80     else
81         return ZWRAP_swap32(value);
82 }
83
84
85 /* ===   Wrapper   === */
86 static int g_ZWRAP_useZSTDcompression = ZWRAP_USE_ZSTD; /* 0 = don't use ZSTD */
87
88 void ZWRAP_useZSTDcompression(int turn_on) { g_ZWRAP_useZSTDcompression = turn_on; }
89
90 int ZWRAP_isUsingZSTDcompression(void) { return g_ZWRAP_useZSTDcompression; }
91
92
93
94 static ZWRAP_decompress_type g_ZWRAPdecompressionType = ZWRAP_AUTO;
95
96 void ZWRAP_setDecompressionType(ZWRAP_decompress_type type) { g_ZWRAPdecompressionType = type; }
97
98 ZWRAP_decompress_type ZWRAP_getDecompressionType(void) { return g_ZWRAPdecompressionType; }
99
100
101
102 const char * zstdVersion(void) { return ZSTD_VERSION_STRING; }
103
104 ZEXTERN const char * ZEXPORT z_zlibVersion _Z_OF((void)) { return zlibVersion();  }
105
106 static void* ZWRAP_allocFunction(void* opaque, size_t size)
107 {
108     z_streamp strm = (z_streamp) opaque;
109     void* address = strm->zalloc(strm->opaque, 1, (uInt)size);
110     /* LOG_WRAPPERC("ZWRAP alloc %p, %d \n", address, (int)size); */
111     return address;
112 }
113
114 static void ZWRAP_freeFunction(void* opaque, void* address)
115 {
116     z_streamp strm = (z_streamp) opaque;
117     strm->zfree(strm->opaque, address);
118    /* if (address) LOG_WRAPPERC("ZWRAP free %p \n", address); */
119 }
120
121 static void* ZWRAP_customMalloc(size_t size, ZSTD_customMem customMem)
122 {
123     if (customMem.customAlloc)
124         return customMem.customAlloc(customMem.opaque, size);
125     return malloc(size);
126 }
127
128 static void* ZWRAP_customCalloc(size_t size, ZSTD_customMem customMem)
129 {
130     if (customMem.customAlloc) {
131         /* calloc implemented as malloc+memset;
132          * not as efficient as calloc, but next best guess for custom malloc */
133         void* const ptr = customMem.customAlloc(customMem.opaque, size);
134         memset(ptr, 0, size);
135         return ptr;
136     }
137     return calloc(1, size);
138 }
139
140 static void ZWRAP_customFree(void* ptr, ZSTD_customMem customMem)
141 {
142     if (ptr!=NULL) {
143         if (customMem.customFree)
144             customMem.customFree(customMem.opaque, ptr);
145         else
146             free(ptr);
147     }
148 }
149
150
151
152 /* ===   Compression   === */
153 typedef enum { ZWRAP_useInit, ZWRAP_useReset, ZWRAP_streamEnd } ZWRAP_state_t;
154
155 typedef struct {
156     ZSTD_CStream* zbc;
157     int compressionLevel;
158     int streamEnd; /* a flag to signal the end of a stream */
159     unsigned long long totalInBytes; /* we need it as strm->total_in can be reset by user */
160     ZSTD_customMem customMem;
161     z_stream allocFunc; /* copy of zalloc, zfree, opaque */
162     ZSTD_inBuffer inBuffer;
163     ZSTD_outBuffer outBuffer;
164     ZWRAP_state_t comprState;
165     unsigned long long pledgedSrcSize;
166 } ZWRAP_CCtx;
167
168 /* typedef ZWRAP_CCtx internal_state; */
169
170
171
172 static size_t ZWRAP_freeCCtx(ZWRAP_CCtx* zwc)
173 {
174     if (zwc==NULL) return 0;   /* support free on NULL */
175     ZSTD_freeCStream(zwc->zbc);
176     ZWRAP_customFree(zwc, zwc->customMem);
177     return 0;
178 }
179
180
181 static ZWRAP_CCtx* ZWRAP_createCCtx(z_streamp strm)
182 {
183     ZWRAP_CCtx* zwc;
184     ZSTD_customMem customMem = { NULL, NULL, NULL };
185
186     if (strm->zalloc && strm->zfree) {
187         customMem.customAlloc = ZWRAP_allocFunction;
188         customMem.customFree = ZWRAP_freeFunction;
189     }
190     customMem.opaque = strm;
191
192     zwc = (ZWRAP_CCtx*)ZWRAP_customCalloc(sizeof(ZWRAP_CCtx), customMem);
193     if (zwc == NULL) return NULL;
194     zwc->allocFunc = *strm;
195     customMem.opaque = &zwc->allocFunc;
196     zwc->customMem = customMem;
197
198     return zwc;
199 }
200
201
202 static int ZWRAP_initializeCStream(ZWRAP_CCtx* zwc, const void* dict, size_t dictSize, unsigned long long pledgedSrcSize)
203 {
204     LOG_WRAPPERC("- ZWRAP_initializeCStream=%p\n", zwc);
205     if (zwc == NULL || zwc->zbc == NULL) return Z_STREAM_ERROR;
206
207     if (!pledgedSrcSize) pledgedSrcSize = zwc->pledgedSrcSize;
208     {   unsigned initErr = 0;
209         ZSTD_parameters const params = ZSTD_getParams(zwc->compressionLevel, pledgedSrcSize, dictSize);
210         ZSTD_CCtx_params* cctxParams = ZSTD_createCCtxParams();
211         if (!cctxParams) return Z_STREAM_ERROR;
212         LOG_WRAPPERC("pledgedSrcSize=%d windowLog=%d chainLog=%d hashLog=%d searchLog=%d minMatch=%d strategy=%d\n",
213                     (int)pledgedSrcSize, params.cParams.windowLog, params.cParams.chainLog, params.cParams.hashLog, params.cParams.searchLog, params.cParams.minMatch, params.cParams.strategy);
214
215         initErr |= ZSTD_isError(ZSTD_CCtx_reset(zwc->zbc, ZSTD_reset_session_only));
216         initErr |= ZSTD_isError(ZSTD_CCtxParams_init_advanced(cctxParams, params));
217         initErr |= ZSTD_isError(ZSTD_CCtx_setParametersUsingCCtxParams(zwc->zbc, cctxParams));
218         initErr |= ZSTD_isError(ZSTD_CCtx_setPledgedSrcSize(zwc->zbc, pledgedSrcSize));
219         initErr |= ZSTD_isError(ZSTD_CCtx_loadDictionary(zwc->zbc, dict, dictSize));
220
221         ZSTD_freeCCtxParams(cctxParams);
222         if (initErr) return Z_STREAM_ERROR;
223     }
224
225     return Z_OK;
226 }
227
228
229 static int ZWRAPC_finishWithError(ZWRAP_CCtx* zwc, z_streamp strm, int error)
230 {
231     LOG_WRAPPERC("- ZWRAPC_finishWithError=%d\n", error);
232     if (zwc) ZWRAP_freeCCtx(zwc);
233     if (strm) strm->state = NULL;
234     return (error) ? error : Z_STREAM_ERROR;
235 }
236
237
238 static int ZWRAPC_finishWithErrorMsg(z_streamp strm, char* message)
239 {
240     ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
241     strm->msg = message;
242     if (zwc == NULL) return Z_STREAM_ERROR;
243
244     return ZWRAPC_finishWithError(zwc, strm, 0);
245 }
246
247
248 int ZWRAP_setPledgedSrcSize(z_streamp strm, unsigned long long pledgedSrcSize)
249 {
250     ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
251     if (zwc == NULL) return Z_STREAM_ERROR;
252
253     zwc->pledgedSrcSize = pledgedSrcSize;
254     zwc->comprState = ZWRAP_useInit;
255     return Z_OK;
256 }
257
258 static struct internal_state* convert_into_sis(void* ptr)
259 {
260     return (struct internal_state*) ptr;
261 }
262
263 ZEXTERN int ZEXPORT z_deflateInit_ _Z_OF((z_streamp strm, int level,
264                                      const char *version, int stream_size))
265 {
266     ZWRAP_CCtx* zwc;
267
268     LOG_WRAPPERC("- deflateInit level=%d\n", level);
269     if (!g_ZWRAP_useZSTDcompression) {
270         return deflateInit_((strm), (level), version, stream_size);
271     }
272
273     zwc = ZWRAP_createCCtx(strm);
274     if (zwc == NULL) return Z_MEM_ERROR;
275
276     if (level == Z_DEFAULT_COMPRESSION)
277         level = ZWRAP_DEFAULT_CLEVEL;
278
279     zwc->streamEnd = 0;
280     zwc->totalInBytes = 0;
281     zwc->compressionLevel = level;
282     strm->state = convert_into_sis(zwc); /* use state which in not used by user */
283     strm->total_in = 0;
284     strm->total_out = 0;
285     strm->adler = 0;
286     return Z_OK;
287 }
288
289
290 ZEXTERN int ZEXPORT z_deflateInit2_ _Z_OF((z_streamp strm, int level, int method,
291                                       int windowBits, int memLevel,
292                                       int strategy, const char *version,
293                                       int stream_size))
294 {
295     if (!g_ZWRAP_useZSTDcompression)
296         return deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size);
297
298     return z_deflateInit_ (strm, level, version, stream_size);
299 }
300
301
302 int ZWRAP_deflateReset_keepDict(z_streamp strm)
303 {
304     LOG_WRAPPERC("- ZWRAP_deflateReset_keepDict\n");
305     if (!g_ZWRAP_useZSTDcompression)
306         return deflateReset(strm);
307
308     { ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
309       if (zwc) {
310           zwc->streamEnd = 0;
311           zwc->totalInBytes = 0;
312       }
313     }
314
315     strm->total_in = 0;
316     strm->total_out = 0;
317     strm->adler = 0;
318     return Z_OK;
319 }
320
321
322 ZEXTERN int ZEXPORT z_deflateReset _Z_OF((z_streamp strm))
323 {
324     LOG_WRAPPERC("- deflateReset\n");
325     if (!g_ZWRAP_useZSTDcompression)
326         return deflateReset(strm);
327
328     ZWRAP_deflateReset_keepDict(strm);
329
330     { ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
331       if (zwc) zwc->comprState = ZWRAP_useInit;
332     }
333     return Z_OK;
334 }
335
336
337 ZEXTERN int ZEXPORT z_deflateSetDictionary _Z_OF((z_streamp strm,
338                                              const Bytef *dictionary,
339                                              uInt  dictLength))
340 {
341     if (!g_ZWRAP_useZSTDcompression) {
342         LOG_WRAPPERC("- deflateSetDictionary\n");
343         return deflateSetDictionary(strm, dictionary, dictLength);
344     }
345
346     {   ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
347         LOG_WRAPPERC("- deflateSetDictionary level=%d\n", (int)zwc->compressionLevel);
348         if (!zwc) return Z_STREAM_ERROR;
349         if (zwc->zbc == NULL) {
350             zwc->zbc = ZSTD_createCStream_advanced(zwc->customMem);
351             if (zwc->zbc == NULL) return ZWRAPC_finishWithError(zwc, strm, 0);
352         }
353         { int res = ZWRAP_initializeCStream(zwc, dictionary, dictLength, ZSTD_CONTENTSIZE_UNKNOWN);
354           if (res != Z_OK) return ZWRAPC_finishWithError(zwc, strm, res); }
355         zwc->comprState = ZWRAP_useReset;
356     }
357
358     return Z_OK;
359 }
360
361
362 ZEXTERN int ZEXPORT z_deflate _Z_OF((z_streamp strm, int flush))
363 {
364     ZWRAP_CCtx* zwc;
365
366     if (!g_ZWRAP_useZSTDcompression) {
367         LOG_WRAPPERC("- deflate1 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\n",
368                     (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
369         return deflate(strm, flush);
370     }
371
372     zwc = (ZWRAP_CCtx*) strm->state;
373     if (zwc == NULL) { LOG_WRAPPERC("zwc == NULL\n"); return Z_STREAM_ERROR; }
374
375     if (zwc->zbc == NULL) {
376         zwc->zbc = ZSTD_createCStream_advanced(zwc->customMem);
377         if (zwc->zbc == NULL) return ZWRAPC_finishWithError(zwc, strm, 0);
378         { int const initErr = ZWRAP_initializeCStream(zwc, NULL, 0, (flush == Z_FINISH) ? strm->avail_in : ZSTD_CONTENTSIZE_UNKNOWN);
379           if (initErr != Z_OK) return ZWRAPC_finishWithError(zwc, strm, initErr); }
380         if (flush != Z_FINISH) zwc->comprState = ZWRAP_useReset;
381     } else {
382         if (zwc->totalInBytes == 0) {
383             if (zwc->comprState == ZWRAP_useReset) {
384                 size_t resetErr = ZSTD_CCtx_reset(zwc->zbc, ZSTD_reset_session_only);
385                 if (ZSTD_isError(resetErr)) {
386                     LOG_WRAPPERC("ERROR: ZSTD_CCtx_reset errorCode=%s\n",
387                                 ZSTD_getErrorName(resetErr));
388                     return ZWRAPC_finishWithError(zwc, strm, 0);
389                 }
390                 resetErr = ZSTD_CCtx_setPledgedSrcSize(zwc->zbc, (flush == Z_FINISH) ? strm->avail_in : zwc->pledgedSrcSize);
391                 if (ZSTD_isError(resetErr)) {
392                     LOG_WRAPPERC("ERROR: ZSTD_CCtx_setPledgedSrcSize errorCode=%s\n",
393                                 ZSTD_getErrorName(resetErr));
394                     return ZWRAPC_finishWithError(zwc, strm, 0);
395                 }
396             } else {
397                 int const res = ZWRAP_initializeCStream(zwc, NULL, 0, (flush == Z_FINISH) ? strm->avail_in : ZSTD_CONTENTSIZE_UNKNOWN);
398                 if (res != Z_OK) return ZWRAPC_finishWithError(zwc, strm, res);
399                 if (flush != Z_FINISH) zwc->comprState = ZWRAP_useReset;
400             }
401         }  /* (zwc->totalInBytes == 0) */
402     }  /* ! (zwc->zbc == NULL) */
403
404     LOG_WRAPPERC("- deflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\n", (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
405     if (strm->avail_in > 0) {
406         zwc->inBuffer.src = strm->next_in;
407         zwc->inBuffer.size = strm->avail_in;
408         zwc->inBuffer.pos = 0;
409         zwc->outBuffer.dst = strm->next_out;
410         zwc->outBuffer.size = strm->avail_out;
411         zwc->outBuffer.pos = 0;
412         { size_t const cErr = ZSTD_compressStream(zwc->zbc, &zwc->outBuffer, &zwc->inBuffer);
413           LOG_WRAPPERC("deflate ZSTD_compressStream srcSize=%d dstCapacity=%d\n", (int)zwc->inBuffer.size, (int)zwc->outBuffer.size);
414           if (ZSTD_isError(cErr)) return ZWRAPC_finishWithError(zwc, strm, 0);
415         }
416         strm->next_out += zwc->outBuffer.pos;
417         strm->total_out += zwc->outBuffer.pos;
418         strm->avail_out -= zwc->outBuffer.pos;
419         strm->total_in += zwc->inBuffer.pos;
420         zwc->totalInBytes += zwc->inBuffer.pos;
421         strm->next_in += zwc->inBuffer.pos;
422         strm->avail_in -= zwc->inBuffer.pos;
423     }
424
425     if (flush == Z_FULL_FLUSH
426 #if ZLIB_VERNUM >= 0x1240
427         || flush == Z_TREES
428 #endif
429         || flush == Z_BLOCK)
430         return ZWRAPC_finishWithErrorMsg(strm, "Z_FULL_FLUSH, Z_BLOCK and Z_TREES are not supported!");
431
432     if (flush == Z_FINISH) {
433         size_t bytesLeft;
434         if (zwc->streamEnd) return Z_STREAM_END;
435         zwc->outBuffer.dst = strm->next_out;
436         zwc->outBuffer.size = strm->avail_out;
437         zwc->outBuffer.pos = 0;
438         bytesLeft = ZSTD_endStream(zwc->zbc, &zwc->outBuffer);
439         LOG_WRAPPERC("deflate ZSTD_endStream dstCapacity=%d bytesLeft=%d\n", (int)strm->avail_out, (int)bytesLeft);
440         if (ZSTD_isError(bytesLeft)) return ZWRAPC_finishWithError(zwc, strm, 0);
441         strm->next_out += zwc->outBuffer.pos;
442         strm->total_out += zwc->outBuffer.pos;
443         strm->avail_out -= zwc->outBuffer.pos;
444         if (bytesLeft == 0) {
445             zwc->streamEnd = 1;
446             LOG_WRAPPERC("Z_STREAM_END2 strm->total_in=%d strm->avail_out=%d strm->total_out=%d\n",
447                         (int)strm->total_in, (int)strm->avail_out, (int)strm->total_out);
448             return Z_STREAM_END;
449     }   }
450     else
451     if (flush == Z_SYNC_FLUSH || flush == Z_PARTIAL_FLUSH) {
452         size_t bytesLeft;
453         zwc->outBuffer.dst = strm->next_out;
454         zwc->outBuffer.size = strm->avail_out;
455         zwc->outBuffer.pos = 0;
456         bytesLeft = ZSTD_flushStream(zwc->zbc, &zwc->outBuffer);
457         LOG_WRAPPERC("deflate ZSTD_flushStream dstCapacity=%d bytesLeft=%d\n", (int)strm->avail_out, (int)bytesLeft);
458         if (ZSTD_isError(bytesLeft)) return ZWRAPC_finishWithError(zwc, strm, 0);
459         strm->next_out += zwc->outBuffer.pos;
460         strm->total_out += zwc->outBuffer.pos;
461         strm->avail_out -= zwc->outBuffer.pos;
462     }
463     LOG_WRAPPERC("- deflate3 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\n", (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
464     return Z_OK;
465 }
466
467
468 ZEXTERN int ZEXPORT z_deflateEnd _Z_OF((z_streamp strm))
469 {
470     if (!g_ZWRAP_useZSTDcompression) {
471         LOG_WRAPPERC("- deflateEnd\n");
472         return deflateEnd(strm);
473     }
474     LOG_WRAPPERC("- deflateEnd total_in=%d total_out=%d\n", (int)(strm->total_in), (int)(strm->total_out));
475     {   size_t errorCode;
476         ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->state;
477         if (zwc == NULL) return Z_OK;  /* structures are already freed */
478         strm->state = NULL;
479         errorCode = ZWRAP_freeCCtx(zwc);
480         if (ZSTD_isError(errorCode)) return Z_STREAM_ERROR;
481     }
482     return Z_OK;
483 }
484
485
486 ZEXTERN uLong ZEXPORT z_deflateBound _Z_OF((z_streamp strm,
487                                        uLong sourceLen))
488 {
489     if (!g_ZWRAP_useZSTDcompression)
490         return deflateBound(strm, sourceLen);
491
492     return ZSTD_compressBound(sourceLen);
493 }
494
495
496 ZEXTERN int ZEXPORT z_deflateParams _Z_OF((z_streamp strm,
497                                       int level,
498                                       int strategy))
499 {
500     if (!g_ZWRAP_useZSTDcompression) {
501         LOG_WRAPPERC("- deflateParams level=%d strategy=%d\n", level, strategy);
502         return deflateParams(strm, level, strategy);
503     }
504
505     return Z_OK;
506 }
507
508
509
510
511
512 /* ===   Decompression   === */
513
514 typedef enum { ZWRAP_ZLIB_STREAM, ZWRAP_ZSTD_STREAM, ZWRAP_UNKNOWN_STREAM } ZWRAP_stream_type;
515
516 typedef struct {
517     ZSTD_DStream* zbd;
518     char headerBuf[16];   /* must be >= ZSTD_frameHeaderSize_min */
519     int errorCount;
520     unsigned long long totalInBytes; /* we need it as strm->total_in can be reset by user */
521     ZWRAP_state_t decompState;
522     ZSTD_inBuffer inBuffer;
523     ZSTD_outBuffer outBuffer;
524
525     /* zlib params */
526     int stream_size;
527     char *version;
528     int windowBits;
529     ZSTD_customMem customMem;
530     z_stream allocFunc; /* just to copy zalloc, zfree, opaque */
531 } ZWRAP_DCtx;
532
533
534 static void ZWRAP_initDCtx(ZWRAP_DCtx* zwd)
535 {
536     zwd->errorCount = 0;
537     zwd->outBuffer.pos = 0;
538     zwd->outBuffer.size = 0;
539 }
540
541 static ZWRAP_DCtx* ZWRAP_createDCtx(z_streamp strm)
542 {
543     ZWRAP_DCtx* zwd;
544     ZSTD_customMem customMem = { NULL, NULL, NULL };
545
546     if (strm->zalloc && strm->zfree) {
547         customMem.customAlloc = ZWRAP_allocFunction;
548         customMem.customFree = ZWRAP_freeFunction;
549     }
550     customMem.opaque = strm;
551
552     zwd = (ZWRAP_DCtx*)ZWRAP_customCalloc(sizeof(ZWRAP_DCtx), customMem);
553     if (zwd == NULL) return NULL;
554     zwd->allocFunc = *strm;
555     customMem.opaque = &zwd->allocFunc;
556     zwd->customMem = customMem;
557
558     ZWRAP_initDCtx(zwd);
559     return zwd;
560 }
561
562 static size_t ZWRAP_freeDCtx(ZWRAP_DCtx* zwd)
563 {
564     if (zwd==NULL) return 0;   /* support free on null */
565     ZSTD_freeDStream(zwd->zbd);
566     ZWRAP_customFree(zwd->version, zwd->customMem);
567     ZWRAP_customFree(zwd, zwd->customMem);
568     return 0;
569 }
570
571
572 int ZWRAP_isUsingZSTDdecompression(z_streamp strm)
573 {
574     if (strm == NULL) return 0;
575     return (strm->reserved == ZWRAP_ZSTD_STREAM);
576 }
577
578
579 static int ZWRAPD_finishWithError(ZWRAP_DCtx* zwd, z_streamp strm, int error)
580 {
581     LOG_WRAPPERD("- ZWRAPD_finishWithError=%d\n", error);
582     ZWRAP_freeDCtx(zwd);
583     strm->state = NULL;
584     return (error) ? error : Z_STREAM_ERROR;
585 }
586
587 static int ZWRAPD_finishWithErrorMsg(z_streamp strm, char* message)
588 {
589     ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;
590     strm->msg = message;
591     if (zwd == NULL) return Z_STREAM_ERROR;
592
593     return ZWRAPD_finishWithError(zwd, strm, 0);
594 }
595
596
597 ZEXTERN int ZEXPORT z_inflateInit_ _Z_OF((z_streamp strm,
598                                      const char* version, int stream_size))
599 {
600     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB) {
601         strm->reserved = ZWRAP_ZLIB_STREAM;
602         return inflateInit(strm);
603     }
604
605     {   ZWRAP_DCtx* const zwd = ZWRAP_createDCtx(strm);
606         LOG_WRAPPERD("- inflateInit\n");
607         if (zwd == NULL) return ZWRAPD_finishWithError(zwd, strm, 0);
608
609         zwd->version = (char*)ZWRAP_customMalloc(strlen(version)+1, zwd->customMem);
610         if (zwd->version == NULL) return ZWRAPD_finishWithError(zwd, strm, 0);
611         strcpy(zwd->version, version);
612
613         zwd->stream_size = stream_size;
614         zwd->totalInBytes = 0;
615         strm->state = convert_into_sis(zwd);
616         strm->total_in = 0;
617         strm->total_out = 0;
618         strm->reserved = ZWRAP_UNKNOWN_STREAM;
619         strm->adler = 0;
620     }
621
622     return Z_OK;
623 }
624
625
626 ZEXTERN int ZEXPORT z_inflateInit2_ _Z_OF((z_streamp strm, int  windowBits,
627                                       const char *version, int stream_size))
628 {
629     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB) {
630         return inflateInit2_(strm, windowBits, version, stream_size);
631     }
632
633     {   int const ret = z_inflateInit_ (strm, version, stream_size);
634         LOG_WRAPPERD("- inflateInit2 windowBits=%d\n", windowBits);
635         if (ret == Z_OK) {
636             ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*)strm->state;
637             if (zwd == NULL) return Z_STREAM_ERROR;
638             zwd->windowBits = windowBits;
639         }
640         return ret;
641     }
642 }
643
644 int ZWRAP_inflateReset_keepDict(z_streamp strm)
645 {
646     LOG_WRAPPERD("- ZWRAP_inflateReset_keepDict\n");
647     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
648         return inflateReset(strm);
649
650     {   ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;
651         if (zwd == NULL) return Z_STREAM_ERROR;
652         ZWRAP_initDCtx(zwd);
653         zwd->decompState = ZWRAP_useReset;
654         zwd->totalInBytes = 0;
655     }
656
657     strm->total_in = 0;
658     strm->total_out = 0;
659     return Z_OK;
660 }
661
662
663 ZEXTERN int ZEXPORT z_inflateReset _Z_OF((z_streamp strm))
664 {
665     LOG_WRAPPERD("- inflateReset\n");
666     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
667         return inflateReset(strm);
668
669     { int const ret = ZWRAP_inflateReset_keepDict(strm);
670       if (ret != Z_OK) return ret; }
671
672     { ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;
673       if (zwd == NULL) return Z_STREAM_ERROR;
674       zwd->decompState = ZWRAP_useInit; }
675
676     return Z_OK;
677 }
678
679
680 #if ZLIB_VERNUM >= 0x1240
681 ZEXTERN int ZEXPORT z_inflateReset2 _Z_OF((z_streamp strm,
682                                       int windowBits))
683 {
684     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
685         return inflateReset2(strm, windowBits);
686
687     {   int const ret = z_inflateReset (strm);
688         if (ret == Z_OK) {
689             ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*)strm->state;
690             if (zwd == NULL) return Z_STREAM_ERROR;
691             zwd->windowBits = windowBits;
692         }
693         return ret;
694     }
695 }
696 #endif
697
698
699 ZEXTERN int ZEXPORT z_inflateSetDictionary _Z_OF((z_streamp strm,
700                                              const Bytef *dictionary,
701                                              uInt  dictLength))
702 {
703     LOG_WRAPPERD("- inflateSetDictionary\n");
704     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
705         return inflateSetDictionary(strm, dictionary, dictLength);
706
707     {   ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;
708         if (zwd == NULL || zwd->zbd == NULL) return Z_STREAM_ERROR;
709         { size_t const resetErr = ZSTD_DCtx_reset(zwd->zbd, ZSTD_reset_session_only);
710           if (ZSTD_isError(resetErr)) return ZWRAPD_finishWithError(zwd, strm, 0); }
711         { size_t const loadErr = ZSTD_DCtx_loadDictionary(zwd->zbd, dictionary, dictLength);
712           if (ZSTD_isError(loadErr)) return ZWRAPD_finishWithError(zwd, strm, 0); }
713         zwd->decompState = ZWRAP_useReset;
714
715         if (zwd->totalInBytes == ZSTD_HEADERSIZE) {
716             zwd->inBuffer.src = zwd->headerBuf;
717             zwd->inBuffer.size = zwd->totalInBytes;
718             zwd->inBuffer.pos = 0;
719             zwd->outBuffer.dst = strm->next_out;
720             zwd->outBuffer.size = 0;
721             zwd->outBuffer.pos = 0;
722             {   size_t const errorCode = ZSTD_decompressStream(zwd->zbd, &zwd->outBuffer, &zwd->inBuffer);
723                 LOG_WRAPPERD("inflateSetDictionary ZSTD_decompressStream errorCode=%d srcSize=%d dstCapacity=%d\n",
724                              (int)errorCode, (int)zwd->inBuffer.size, (int)zwd->outBuffer.size);
725                 if (zwd->inBuffer.pos < zwd->outBuffer.size || ZSTD_isError(errorCode)) {
726                     LOG_WRAPPERD("ERROR: ZSTD_decompressStream %s\n",
727                                  ZSTD_getErrorName(errorCode));
728                     return ZWRAPD_finishWithError(zwd, strm, 0);
729     }   }   }   }
730
731     return Z_OK;
732 }
733
734
735 ZEXTERN int ZEXPORT z_inflate _Z_OF((z_streamp strm, int flush))
736 {
737     ZWRAP_DCtx* zwd;
738
739     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved) {
740         int const result = inflate(strm, flush);
741         LOG_WRAPPERD("- inflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\n",
742                      (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, result);
743         return result;
744     }
745
746     if (strm->avail_in <= 0) return Z_OK;
747
748     zwd = (ZWRAP_DCtx*) strm->state;
749     LOG_WRAPPERD("- inflate1 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d\n",
750                  (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
751
752     if (zwd == NULL) return Z_STREAM_ERROR;
753     if (zwd->decompState == ZWRAP_streamEnd) return Z_STREAM_END;
754
755     if (zwd->totalInBytes < ZLIB_HEADERSIZE) {
756         if (zwd->totalInBytes == 0 && strm->avail_in >= ZLIB_HEADERSIZE) {
757             if (ZWRAP_readLE32(strm->next_in) != ZSTD_MAGICNUMBER) {
758                 {   int const initErr = (zwd->windowBits) ?
759                                 inflateInit2_(strm, zwd->windowBits, zwd->version, zwd->stream_size) :
760                                 inflateInit_(strm, zwd->version, zwd->stream_size);
761                     LOG_WRAPPERD("ZLIB inflateInit errorCode=%d\n", initErr);
762                     if (initErr != Z_OK) return ZWRAPD_finishWithError(zwd, strm, initErr);
763                 }
764
765                 strm->reserved = ZWRAP_ZLIB_STREAM;
766                 { size_t const freeErr = ZWRAP_freeDCtx(zwd);
767                   if (ZSTD_isError(freeErr)) goto error; }
768
769                 {   int const result = (flush == Z_INFLATE_SYNC) ?
770                                         inflateSync(strm) :
771                                         inflate(strm, flush);
772                     LOG_WRAPPERD("- inflate3 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\n",
773                                  (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, res);
774                     return result;
775             }   }
776         } else {  /* ! (zwd->totalInBytes == 0 && strm->avail_in >= ZLIB_HEADERSIZE) */
777             size_t const srcSize = MIN(strm->avail_in, ZLIB_HEADERSIZE - zwd->totalInBytes);
778             memcpy(zwd->headerBuf+zwd->totalInBytes, strm->next_in, srcSize);
779             strm->total_in += srcSize;
780             zwd->totalInBytes += srcSize;
781             strm->next_in += srcSize;
782             strm->avail_in -= srcSize;
783             if (zwd->totalInBytes < ZLIB_HEADERSIZE) return Z_OK;
784
785             if (ZWRAP_readLE32(zwd->headerBuf) != ZSTD_MAGICNUMBER) {
786                 z_stream strm2;
787                 strm2.next_in = strm->next_in;
788                 strm2.avail_in = strm->avail_in;
789                 strm2.next_out = strm->next_out;
790                 strm2.avail_out = strm->avail_out;
791
792                 {   int const initErr = (zwd->windowBits) ?
793                                 inflateInit2_(strm, zwd->windowBits, zwd->version, zwd->stream_size) :
794                                 inflateInit_(strm, zwd->version, zwd->stream_size);
795                     LOG_WRAPPERD("ZLIB inflateInit errorCode=%d\n", initErr);
796                     if (initErr != Z_OK) return ZWRAPD_finishWithError(zwd, strm, initErr);
797                 }
798
799                 /* inflate header */
800                 strm->next_in = (unsigned char*)zwd->headerBuf;
801                 strm->avail_in = ZLIB_HEADERSIZE;
802                 strm->avail_out = 0;
803                 {   int const dErr = inflate(strm, Z_NO_FLUSH);
804                     LOG_WRAPPERD("ZLIB inflate errorCode=%d strm->avail_in=%d\n",
805                                   dErr, (int)strm->avail_in);
806                     if (dErr != Z_OK)
807                         return ZWRAPD_finishWithError(zwd, strm, dErr);
808                 }
809                 if (strm->avail_in > 0) goto error;
810
811                 strm->next_in = strm2.next_in;
812                 strm->avail_in = strm2.avail_in;
813                 strm->next_out = strm2.next_out;
814                 strm->avail_out = strm2.avail_out;
815
816                 strm->reserved = ZWRAP_ZLIB_STREAM; /* mark as zlib stream */
817                 { size_t const freeErr = ZWRAP_freeDCtx(zwd);
818                   if (ZSTD_isError(freeErr)) goto error; }
819
820                 {   int const result = (flush == Z_INFLATE_SYNC) ?
821                                        inflateSync(strm) :
822                                        inflate(strm, flush);
823                     LOG_WRAPPERD("- inflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\n",
824                                  (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, res);
825                     return result;
826         }   }   }  /* if ! (zwd->totalInBytes == 0 && strm->avail_in >= ZLIB_HEADERSIZE) */
827     }  /* (zwd->totalInBytes < ZLIB_HEADERSIZE) */
828
829     strm->reserved = ZWRAP_ZSTD_STREAM; /* mark as zstd steam */
830
831     if (flush == Z_INFLATE_SYNC) { strm->msg = "inflateSync is not supported!"; goto error; }
832
833     if (!zwd->zbd) {
834         zwd->zbd = ZSTD_createDStream_advanced(zwd->customMem);
835         if (zwd->zbd == NULL) { LOG_WRAPPERD("ERROR: ZSTD_createDStream_advanced\n"); goto error; }
836         zwd->decompState = ZWRAP_useInit;
837     }
838
839     if (zwd->totalInBytes < ZSTD_HEADERSIZE) {
840         if (zwd->totalInBytes == 0 && strm->avail_in >= ZSTD_HEADERSIZE) {
841             if (zwd->decompState == ZWRAP_useInit) {
842                 size_t const initErr = ZSTD_initDStream(zwd->zbd);
843                 if (ZSTD_isError(initErr)) {
844                     LOG_WRAPPERD("ERROR: ZSTD_initDStream errorCode=%s\n",
845                                  ZSTD_getErrorName(initErr));
846                     goto error;
847                 }
848             } else {
849                 size_t const resetErr = ZSTD_DCtx_reset(zwd->zbd, ZSTD_reset_session_only);
850                 if (ZSTD_isError(resetErr)) goto error;
851             }
852         } else {
853             size_t const srcSize = MIN(strm->avail_in, ZSTD_HEADERSIZE - zwd->totalInBytes);
854             memcpy(zwd->headerBuf+zwd->totalInBytes, strm->next_in, srcSize);
855             strm->total_in += srcSize;
856             zwd->totalInBytes += srcSize;
857             strm->next_in += srcSize;
858             strm->avail_in -= srcSize;
859             if (zwd->totalInBytes < ZSTD_HEADERSIZE) return Z_OK;
860
861             if (zwd->decompState == ZWRAP_useInit) {
862                 size_t const initErr = ZSTD_initDStream(zwd->zbd);
863                 if (ZSTD_isError(initErr)) {
864                     LOG_WRAPPERD("ERROR: ZSTD_initDStream errorCode=%s\n",
865                                 ZSTD_getErrorName(initErr));
866                     goto error;
867                 }
868             } else {
869                 size_t const resetErr = ZSTD_DCtx_reset(zwd->zbd, ZSTD_reset_session_only);
870                 if (ZSTD_isError(resetErr)) goto error;
871             }
872
873             zwd->inBuffer.src = zwd->headerBuf;
874             zwd->inBuffer.size = ZSTD_HEADERSIZE;
875             zwd->inBuffer.pos = 0;
876             zwd->outBuffer.dst = strm->next_out;
877             zwd->outBuffer.size = 0;
878             zwd->outBuffer.pos = 0;
879             {   size_t const dErr = ZSTD_decompressStream(zwd->zbd, &zwd->outBuffer, &zwd->inBuffer);
880                 LOG_WRAPPERD("inflate ZSTD_decompressStream1 errorCode=%d srcSize=%d dstCapacity=%d\n",
881                             (int)dErr, (int)zwd->inBuffer.size, (int)zwd->outBuffer.size);
882                 if (ZSTD_isError(dErr)) {
883                     LOG_WRAPPERD("ERROR: ZSTD_decompressStream1 %s\n", ZSTD_getErrorName(dErr));
884                     goto error;
885             }   }
886             if (zwd->inBuffer.pos != zwd->inBuffer.size) goto error; /* not consumed */
887         }
888     }   /* (zwd->totalInBytes < ZSTD_HEADERSIZE) */
889
890     zwd->inBuffer.src = strm->next_in;
891     zwd->inBuffer.size = strm->avail_in;
892     zwd->inBuffer.pos = 0;
893     zwd->outBuffer.dst = strm->next_out;
894     zwd->outBuffer.size = strm->avail_out;
895     zwd->outBuffer.pos = 0;
896     {   size_t const dErr = ZSTD_decompressStream(zwd->zbd, &zwd->outBuffer, &zwd->inBuffer);
897         LOG_WRAPPERD("inflate ZSTD_decompressStream2 errorCode=%d srcSize=%d dstCapacity=%d\n",
898                     (int)dErr, (int)strm->avail_in, (int)strm->avail_out);
899         if (ZSTD_isError(dErr)) {
900             zwd->errorCount++;
901             LOG_WRAPPERD("ERROR: ZSTD_decompressStream2 %s zwd->errorCount=%d\n",
902                         ZSTD_getErrorName(dErr), zwd->errorCount);
903             if (zwd->errorCount<=1) return Z_NEED_DICT; else goto error;
904         }
905         LOG_WRAPPERD("inflate inBuffer.pos=%d inBuffer.size=%d outBuffer.pos=%d outBuffer.size=%d o\n",
906                     (int)zwd->inBuffer.pos, (int)zwd->inBuffer.size, (int)zwd->outBuffer.pos, (int)zwd->outBuffer.size);
907         strm->next_out += zwd->outBuffer.pos;
908         strm->total_out += zwd->outBuffer.pos;
909         strm->avail_out -= zwd->outBuffer.pos;
910         strm->total_in += zwd->inBuffer.pos;
911         zwd->totalInBytes += zwd->inBuffer.pos;
912         strm->next_in += zwd->inBuffer.pos;
913         strm->avail_in -= zwd->inBuffer.pos;
914         if (dErr == 0) {
915             LOG_WRAPPERD("inflate Z_STREAM_END1 avail_in=%d avail_out=%d total_in=%d total_out=%d\n",
916                         (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
917             zwd->decompState = ZWRAP_streamEnd;
918             return Z_STREAM_END;
919         }
920     }  /* dErr lifetime */
921
922     LOG_WRAPPERD("- inflate2 flush=%d avail_in=%d avail_out=%d total_in=%d total_out=%d res=%d\n",
923                 (int)flush, (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out, Z_OK);
924     return Z_OK;
925
926 error:
927     return ZWRAPD_finishWithError(zwd, strm, 0);
928 }
929
930
931 ZEXTERN int ZEXPORT z_inflateEnd _Z_OF((z_streamp strm))
932 {
933     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
934         return inflateEnd(strm);
935
936     LOG_WRAPPERD("- inflateEnd total_in=%d total_out=%d\n",
937                 (int)(strm->total_in), (int)(strm->total_out));
938     {   ZWRAP_DCtx* const zwd = (ZWRAP_DCtx*) strm->state;
939         if (zwd == NULL) return Z_OK;  /* structures are already freed */
940         { size_t const freeErr = ZWRAP_freeDCtx(zwd);
941           if (ZSTD_isError(freeErr)) return Z_STREAM_ERROR; }
942         strm->state = NULL;
943     }
944     return Z_OK;
945 }
946
947
948 ZEXTERN int ZEXPORT z_inflateSync _Z_OF((z_streamp strm))
949 {
950     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved) {
951         return inflateSync(strm);
952     }
953
954     return z_inflate(strm, Z_INFLATE_SYNC);
955 }
956
957
958
959 /* Advanced compression functions */
960 ZEXTERN int ZEXPORT z_deflateCopy _Z_OF((z_streamp dest,
961                                     z_streamp source))
962 {
963     if (!g_ZWRAP_useZSTDcompression)
964         return deflateCopy(dest, source);
965     return ZWRAPC_finishWithErrorMsg(source, "deflateCopy is not supported!");
966 }
967
968
969 ZEXTERN int ZEXPORT z_deflateTune _Z_OF((z_streamp strm,
970                                     int good_length,
971                                     int max_lazy,
972                                     int nice_length,
973                                     int max_chain))
974 {
975     if (!g_ZWRAP_useZSTDcompression)
976         return deflateTune(strm, good_length, max_lazy, nice_length, max_chain);
977     return ZWRAPC_finishWithErrorMsg(strm, "deflateTune is not supported!");
978 }
979
980
981 #if ZLIB_VERNUM >= 0x1260
982 ZEXTERN int ZEXPORT z_deflatePending _Z_OF((z_streamp strm,
983                                        unsigned *pending,
984                                        int *bits))
985 {
986     if (!g_ZWRAP_useZSTDcompression)
987         return deflatePending(strm, pending, bits);
988     return ZWRAPC_finishWithErrorMsg(strm, "deflatePending is not supported!");
989 }
990 #endif
991
992
993 ZEXTERN int ZEXPORT z_deflatePrime _Z_OF((z_streamp strm,
994                                      int bits,
995                                      int value))
996 {
997     if (!g_ZWRAP_useZSTDcompression)
998         return deflatePrime(strm, bits, value);
999     return ZWRAPC_finishWithErrorMsg(strm, "deflatePrime is not supported!");
1000 }
1001
1002
1003 ZEXTERN int ZEXPORT z_deflateSetHeader _Z_OF((z_streamp strm,
1004                                          gz_headerp head))
1005 {
1006     if (!g_ZWRAP_useZSTDcompression)
1007         return deflateSetHeader(strm, head);
1008     return ZWRAPC_finishWithErrorMsg(strm, "deflateSetHeader is not supported!");
1009 }
1010
1011
1012
1013
1014 /* Advanced decompression functions */
1015 #if ZLIB_VERNUM >= 0x1280
1016 ZEXTERN int ZEXPORT z_inflateGetDictionary _Z_OF((z_streamp strm,
1017                                              Bytef *dictionary,
1018                                              uInt  *dictLength))
1019 {
1020     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
1021         return inflateGetDictionary(strm, dictionary, dictLength);
1022     return ZWRAPD_finishWithErrorMsg(strm, "inflateGetDictionary is not supported!");
1023 }
1024 #endif
1025
1026
1027 ZEXTERN int ZEXPORT z_inflateCopy _Z_OF((z_streamp dest,
1028                                     z_streamp source))
1029 {
1030     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !source->reserved)
1031         return inflateCopy(dest, source);
1032     return ZWRAPD_finishWithErrorMsg(source, "inflateCopy is not supported!");
1033 }
1034
1035
1036 #if ZLIB_VERNUM >= 0x1240
1037 ZEXTERN long ZEXPORT z_inflateMark _Z_OF((z_streamp strm))
1038 {
1039     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
1040         return inflateMark(strm);
1041     return ZWRAPD_finishWithErrorMsg(strm, "inflateMark is not supported!");
1042 }
1043 #endif
1044
1045
1046 ZEXTERN int ZEXPORT z_inflatePrime _Z_OF((z_streamp strm,
1047                                      int bits,
1048                                      int value))
1049 {
1050     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
1051         return inflatePrime(strm, bits, value);
1052     return ZWRAPD_finishWithErrorMsg(strm, "inflatePrime is not supported!");
1053 }
1054
1055
1056 ZEXTERN int ZEXPORT z_inflateGetHeader _Z_OF((z_streamp strm,
1057                                          gz_headerp head))
1058 {
1059     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
1060         return inflateGetHeader(strm, head);
1061     return ZWRAPD_finishWithErrorMsg(strm, "inflateGetHeader is not supported!");
1062 }
1063
1064
1065 ZEXTERN int ZEXPORT z_inflateBackInit_ _Z_OF((z_streamp strm, int windowBits,
1066                                          unsigned char FAR *window,
1067                                          const char *version,
1068                                          int stream_size))
1069 {
1070     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
1071         return inflateBackInit_(strm, windowBits, window, version, stream_size);
1072     return ZWRAPD_finishWithErrorMsg(strm, "inflateBackInit is not supported!");
1073 }
1074
1075
1076 ZEXTERN int ZEXPORT z_inflateBack _Z_OF((z_streamp strm,
1077                                     in_func in, void FAR *in_desc,
1078                                     out_func out, void FAR *out_desc))
1079 {
1080     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
1081         return inflateBack(strm, in, in_desc, out, out_desc);
1082     return ZWRAPD_finishWithErrorMsg(strm, "inflateBack is not supported!");
1083 }
1084
1085
1086 ZEXTERN int ZEXPORT z_inflateBackEnd _Z_OF((z_streamp strm))
1087 {
1088     if (g_ZWRAPdecompressionType == ZWRAP_FORCE_ZLIB || !strm->reserved)
1089         return inflateBackEnd(strm);
1090     return ZWRAPD_finishWithErrorMsg(strm, "inflateBackEnd is not supported!");
1091 }
1092
1093
1094 ZEXTERN uLong ZEXPORT z_zlibCompileFlags _Z_OF((void)) { return zlibCompileFlags(); }
1095
1096
1097
1098                     /* ===   utility functions  === */
1099 #ifndef Z_SOLO
1100
1101 ZEXTERN int ZEXPORT z_compress _Z_OF((Bytef *dest,   uLongf *destLen,
1102                                  const Bytef *source, uLong sourceLen))
1103 {
1104     if (!g_ZWRAP_useZSTDcompression)
1105         return compress(dest, destLen, source, sourceLen);
1106
1107     {   size_t dstCapacity = *destLen;
1108         size_t const cSize = ZSTD_compress(dest, dstCapacity,
1109                                            source, sourceLen,
1110                                            ZWRAP_DEFAULT_CLEVEL);
1111         LOG_WRAPPERD("z_compress sourceLen=%d dstCapacity=%d\n",
1112                     (int)sourceLen, (int)dstCapacity);
1113         if (ZSTD_isError(cSize)) return Z_STREAM_ERROR;
1114         *destLen = cSize;
1115     }
1116     return Z_OK;
1117 }
1118
1119
1120 ZEXTERN int ZEXPORT z_compress2 _Z_OF((Bytef *dest,   uLongf *destLen,
1121                                   const Bytef *source, uLong sourceLen,
1122                                   int level))
1123 {
1124     if (!g_ZWRAP_useZSTDcompression)
1125         return compress2(dest, destLen, source, sourceLen, level);
1126
1127     { size_t dstCapacity = *destLen;
1128       size_t const cSize = ZSTD_compress(dest, dstCapacity, source, sourceLen, level);
1129       if (ZSTD_isError(cSize)) return Z_STREAM_ERROR;
1130       *destLen = cSize;
1131     }
1132     return Z_OK;
1133 }
1134
1135
1136 ZEXTERN uLong ZEXPORT z_compressBound _Z_OF((uLong sourceLen))
1137 {
1138     if (!g_ZWRAP_useZSTDcompression)
1139         return compressBound(sourceLen);
1140
1141     return ZSTD_compressBound(sourceLen);
1142 }
1143
1144
1145 ZEXTERN int ZEXPORT z_uncompress _Z_OF((Bytef *dest,   uLongf *destLen,
1146                                    const Bytef *source, uLong sourceLen))
1147 {
1148     if (!ZSTD_isFrame(source, sourceLen))
1149         return uncompress(dest, destLen, source, sourceLen);
1150
1151     { size_t dstCapacity = *destLen;
1152       size_t const dSize = ZSTD_decompress(dest, dstCapacity, source, sourceLen);
1153       if (ZSTD_isError(dSize)) return Z_STREAM_ERROR;
1154       *destLen = dSize;
1155      }
1156     return Z_OK;
1157 }
1158
1159 #endif /* !Z_SOLO */
1160
1161
1162                         /* checksum functions */
1163
1164 ZEXTERN uLong ZEXPORT z_adler32 _Z_OF((uLong adler, const Bytef *buf, uInt len))
1165 {
1166     return adler32(adler, buf, len);
1167 }
1168
1169 ZEXTERN uLong ZEXPORT z_crc32   _Z_OF((uLong crc, const Bytef *buf, uInt len))
1170 {
1171     return crc32(crc, buf, len);
1172 }
1173
1174
1175 #if ZLIB_VERNUM >= 0x12B0
1176 ZEXTERN uLong ZEXPORT z_adler32_z _Z_OF((uLong adler, const Bytef *buf, z_size_t len))
1177 {
1178     return adler32_z(adler, buf, len);
1179 }
1180
1181 ZEXTERN uLong ZEXPORT z_crc32_z _Z_OF((uLong crc, const Bytef *buf, z_size_t len))
1182 {
1183     return crc32_z(crc, buf, len);
1184 }
1185 #endif
1186
1187
1188 #if ZLIB_VERNUM >= 0x1270
1189 ZEXTERN const z_crc_t FAR * ZEXPORT z_get_crc_table    _Z_OF((void))
1190 {
1191     return get_crc_table();
1192 }
1193 #endif
1194
1195                         /* Error function */
1196 ZEXTERN const char * ZEXPORT z_zError _Z_OF((int err))
1197 {
1198     /* Just use zlib Error function */
1199     return zError(err);
1200 }