]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
added zlibWrapper - zstd wrapper for zlib
authorinikep <inikep@gmail.com>
Thu, 12 May 2016 15:15:41 +0000 (17:15 +0200)
committerinikep <inikep@gmail.com>
Thu, 12 May 2016 15:15:41 +0000 (17:15 +0200)
programs/util.h
zlibWrapper/.gitignore [new file with mode: 0644]
zlibWrapper/Makefile [new file with mode: 0644]
zlibWrapper/README.md [new file with mode: 0644]
zlibWrapper/examples/example.c [new file with mode: 0644]
zlibWrapper/examples/example_original.c [new file with mode: 0644]
zlibWrapper/zstd_zlibwrapper.c [new file with mode: 0644]
zlibWrapper/zstd_zlibwrapper.h [new file with mode: 0644]

index 76273412b4373c083308d96b068b33690cb77029..d791a2c7138c67cd35bd7987bb8366bc5af6c7d8 100644 (file)
@@ -281,7 +281,7 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_
         return 0;
     }
  
-    while (entry = readdir(dir)) {
+    while ((entry = readdir(dir)) != NULL) {
         if (strcmp (entry->d_name, "..") == 0 ||
             strcmp (entry->d_name, ".") == 0) continue;
         pathLength = snprintf(path, PATH_MAX, "%s/%s", dirName, entry->d_name);
diff --git a/zlibWrapper/.gitignore b/zlibWrapper/.gitignore
new file mode 100644 (file)
index 0000000..5647351
--- /dev/null
@@ -0,0 +1,26 @@
+# Object files
+*.o
+*.ko
+
+# Libraries
+*.lib
+*.a
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# Default result files
+_*
+
+# Misc files
+*.bat
+*.zip
+examples/example2.c
diff --git a/zlibWrapper/Makefile b/zlibWrapper/Makefile
new file mode 100644 (file)
index 0000000..fd45ee6
--- /dev/null
@@ -0,0 +1,54 @@
+# Makefile for example of using zstd wrapper for zlib
+#
+# make - compiles statically and dynamically linked examples/example.c
+# make test testdll - compiles and runs statically and dynamically linked examples/example.c
+# make LOC=-DZWRAP_USE_ZSTD=1 - compiles statically and dynamically linked examples/example.c with zstd compression turned on
+
+
+# Paths to static and dynamic zlib and zstd libraries
+ifneq (,$(filter Windows%,$(OS)))
+STATICLIB = ../../zlib/libz.a ../lib/libzstd.a
+IMPLIB    = ../../zlib/libz.dll.a ../lib/libzstd.a
+else
+STATICLIB = -static -lz ../lib/libzstd.a
+IMPLIB    = -lz ../lib/libzstd.a
+endif
+
+ZLIBWRAPPER_PATH = .
+EXAMPLE_PATH = examples/
+CC = gcc
+CFLAGS = $(LOC) -I../lib/common -I$(ZLIBWRAPPER_PATH) -O3 -Wall -std=gnu89
+LDFLAGS = $(LOC)
+RM = rm -f
+
+
+all: example example_d
+
+test: example
+       ./example
+
+testdll: example_d
+       ./example_d
+
+.c.o:
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+example: $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o
+       $(CC) $(LDFLAGS) -o $@ $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(STATICLIB)
+
+example_d: $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o
+       $(CC) $(LDFLAGS) -o $@ $(EXAMPLE_PATH)/example.o $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o $(IMPLIB)
+
+$(EXAMPLE_PATH)/example.o: $(EXAMPLE_PATH)/example.c
+       $(CC) $(CFLAGS) -I. -c -o $@ $(EXAMPLE_PATH)/example.c
+
+$(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.o: $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.c $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.h
+       $(CC) $(CFLAGS) -I. -c -o $@ $(ZLIBWRAPPER_PATH)/zstd_zlibwrapper.c
+
+clean:
+       -$(RM) $(ZLIBWRAPPER_PATH)/*.o
+       -$(RM) $(EXAMPLE_PATH)/*.o
+       -$(RM) *.o
+       -$(RM) *.exe
+       -$(RM) foo.gz
+
diff --git a/zlibWrapper/README.md b/zlibWrapper/README.md
new file mode 100644 (file)
index 0000000..5572e3e
--- /dev/null
@@ -0,0 +1,104 @@
+zstd wrapper for zlib
+================================
+
+The main objective of creating a zstd wrapper for zlib is to allow a quick and smooth transition to zstd for projects already using zlib.
+
+#### Required files
+
+To build the zstd wrapper for zlib the following files are required:
+- zlib.h
+- a static or dynamic zlib library
+- zlibWrapper/zstd_zlibwrapper.h
+- zlibWrapper/zstd_zlibwrapper.c
+- a static or dynamic zstd library
+
+The first two files are required by all projects using zlib and they are not included with the zstd distribution.
+The further files are supplied with the zstd distribution.
+
+
+#### Embedding the zstd wrapper within your project
+
+Let's assume that your project that uses zlib is compiled with:
+```gcc project.o -lz```
+
+To compile the zstd wrapper with your project you have to do the following:
+- change all references with ```#include "zlib.h"``` to ```#include "zstd_zlibwrapper.h"```
+- compile your project with zlib_wrapper.c and a static or dynamic zstd library
+
+The linking should be changed to:
+```gcc project.o zlib_wrapper.o -lz -lzstd```
+
+
+#### Using the zstd wrapper with your project
+
+After embedding the zstd wrapper within your project the zstd library is turned off by default.
+Your project should work as before with zlib. There are two options to enable zstd compression:
+- compilation with ```-DZWRAP_USE_ZSTD=1``` (or using ```#define ZWRAP_USE_ZSTD 1``` before ```#include "zstd_zlibwrapper.h"```)
+- using the ```void useZSTD(int turn_on)``` function (declared in ```#include "zstd_zlibwrapper.h"```)
+There is no switch for zstd decompression because zlib and zstd streams are automatically detected and decompressed using a proper library.
+
+
+#### Example
+We have take the file ```test\example.c``` from the zlib library distribution and copied it to ```zlibWrapper\examples\example.c```.
+After compilation and execution it shows the following results: 
+```
+zlib version 1.2.8 = 0x1280, compile flags = 0x65
+uncompress(): hello, hello!
+gzread(): hello, hello!
+gzgets() after gzseek:  hello!
+inflate(): hello, hello!
+large_inflate(): OK
+after inflateSync(): hello, hello!
+inflate with dictionary: hello, hello!
+```
+Then we have compiled the example.c file with ```-DZWRAP_USE_ZSTD=1``` and linked with ```zlib_wrapper.o -lzstd```.
+We have also turned of the following functions: test_gzio, test_flush, test_sync which use currently unsupported features.
+It shows the following results:
+```
+zlib version 1.2.8 = 0x1280, compile flags = 0x65
+uncompress(): hello, hello!
+inflate(): hello, hello!
+large_inflate(): OK
+inflate with dictionary: hello, hello!
+```
+The script used for compilation can be found at [zlibWrapper\Makefile](.\Makefile).
+
+
+#### Compatibility issues
+After enabling zstd compression not all functions are supported. Unsupported methods when called print error message and return an error value.
+
+Supported methods:
+- deflateInit
+- deflate (with exception of Z_FULL_FLUSH)
+- deflateSetDictionary
+- deflateEnd
+- deflateBound
+- inflateInit
+- inflate
+- inflateSetDictionary
+- compress
+- compress2
+- compressBound
+- uncompress
+
+Ignored methods (they do nothing):
+- deflateParams
+
+Unsupported methods:
+- gzip file access functions
+- deflateCopy
+- deflateReset
+- deflateTune
+- deflatePending
+- deflatePrime
+- deflateSetHeader
+- inflateGetDictionary
+- inflateCopy
+- inflateReset
+- inflateReset2
+- inflatePrime
+- inflateMark
+- inflateGetHeader
+- inflateBackInit
+- inflateBack
+- inflateBackEnd
diff --git a/zlibWrapper/examples/example.c b/zlibWrapper/examples/example.c
new file mode 100644 (file)
index 0000000..fe6c80a
--- /dev/null
@@ -0,0 +1,607 @@
+/* the file contains minimal changes required to be compiled with zstd wrapper for zlib */
+
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-2006, 2011 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zstd_zlibwrapper.h"
+#include <stdio.h>
+
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+#  define TESTFILE "foo-gz"
+#else
+#  define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+    if (err != Z_OK) { \
+        fprintf(stderr, "%s error: %d\n", msg, err); \
+        exit(1); \
+    } \
+}
+
+z_const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_deflate       OF((Byte *compr, uLong comprLen));
+void test_inflate       OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_flush         OF((Byte *compr, uLong *comprLen));
+void test_sync          OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate  OF((Byte *compr, uLong comprLen));
+void test_dict_inflate  OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+int  main               OF((int argc, char *argv[]));
+
+
+#ifdef Z_SOLO
+
+void *myalloc OF((void *, unsigned, unsigned));
+void myfree OF((void *, void *));
+
+void *myalloc(q, n, m)
+    void *q;
+    unsigned n, m;
+{
+    q = Z_NULL;
+    return calloc(n, m);
+}
+
+void myfree(void *q, void *p)
+{
+    q = Z_NULL;
+    free(p);
+}
+
+static alloc_func zalloc = myalloc;
+static free_func zfree = myfree;
+
+#else /* !Z_SOLO */
+
+static alloc_func zalloc = (alloc_func)0;
+static free_func zfree = (free_func)0;
+
+void test_compress      OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_gzio          OF((const char *fname,
+                            Byte *uncompr, uLong uncomprLen));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    uLong len = (uLong)strlen(hello)+1;
+
+    err = compress(compr, &comprLen, (const Bytef*)hello, len);
+    CHECK_ERR(err, "compress");
+
+    strcpy((char*)uncompr, "garbage");
+
+    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+    CHECK_ERR(err, "uncompress");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad uncompress\n");
+        exit(1);
+    } else {
+        printf("uncompress(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(fname, uncompr, uncomprLen)
+    const char *fname; /* compressed file name */
+    Byte *uncompr;
+    uLong uncomprLen;
+{
+#ifdef NO_GZCOMPRESS
+    fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
+#else
+    int err;
+    int len = (int)strlen(hello)+1;
+    gzFile file;
+    z_off_t pos;
+
+    file = gzopen(fname, "wb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+        exit(1);
+    }
+    gzputc(file, 'h');
+    if (gzputs(file, "ello") != 4) {
+        fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (gzprintf(file, ", %s!", "hello") != 8) {
+        fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+    gzclose(file);
+
+    file = gzopen(fname, "rb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+        exit(1);
+    }
+    strcpy((char*)uncompr, "garbage");
+
+    if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
+        fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+        exit(1);
+    } else {
+        printf("gzread(): %s\n", (char*)uncompr);
+    }
+
+    pos = gzseek(file, -8L, SEEK_CUR);
+    if (pos != 6 || gztell(file) != pos) {
+        fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+                (long)pos, (long)gztell(file));
+        exit(1);
+    }
+
+    if (gzgetc(file) != ' ') {
+        fprintf(stderr, "gzgetc error\n");
+        exit(1);
+    }
+
+    if (gzungetc(' ', file) != ' ') {
+        fprintf(stderr, "gzungetc error\n");
+        exit(1);
+    }
+
+    gzgets(file, (char*)uncompr, (int)uncomprLen);
+    if (strlen((char*)uncompr) != 7) { /* " hello!" */
+        fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (strcmp((char*)uncompr, hello + 6)) {
+        fprintf(stderr, "bad gzgets after gzseek\n");
+        exit(1);
+    } else {
+        printf("gzgets() after gzseek: %s\n", (char*)uncompr);
+    }
+
+    gzclose(file);
+#endif
+}
+
+#endif /* Z_SOLO */
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    uLong len = (uLong)strlen(hello)+1;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (z_const unsigned char *)hello;
+    c_stream.next_out = compr;
+
+    while (c_stream.total_in != len && c_stream.total_out < comprLen) {
+        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+        err = deflate(&c_stream, Z_NO_FLUSH);
+        CHECK_ERR(err, "deflate");
+    }
+    /* Finish the stream, still forcing small buffers: */
+    for (;;) {
+        c_stream.avail_out = 1;
+        err = deflate(&c_stream, Z_FINISH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "deflate");
+    }
+
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 0;
+    d_stream.next_out = uncompr;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate\n");
+        exit(1);
+    } else {
+        printf("inflate(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_SPEED);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    /* At this point, uncompr is still mostly zeroes, so it should compress
+     * very well:
+     */
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+    if (c_stream.avail_in != 0) {
+        fprintf(stderr, "deflate not greedy\n");
+        exit(1);
+    }
+
+    /* Feed in already compressed data and switch to no compression: */
+    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+    c_stream.next_in = compr;
+    c_stream.avail_in = (uInt)comprLen/2;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    /* Switch back to compressing mode: */
+    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+        exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    for (;;) {
+        d_stream.next_out = uncompr;            /* discard the output */
+        d_stream.avail_out = (uInt)uncomprLen;
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "large inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+        exit(1);
+    } else {
+        printf("large_inflate(): OK\n");
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+    Byte *compr;
+    uLong *comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    uInt len = (uInt)strlen(hello)+1;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (z_const unsigned char *)hello;
+    c_stream.next_out = compr;
+    c_stream.avail_in = 3;
+    c_stream.avail_out = (uInt)*comprLen;
+    err = deflate(&c_stream, Z_FULL_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    compr[3]++; /* force an error in first compressed block */
+    c_stream.avail_in = len - 3;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        CHECK_ERR(err, "deflate");
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+
+    *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 2; /* just read the zlib header */
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    inflate(&d_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "inflate");
+
+    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
+    err = inflateSync(&d_stream);           /* but skip the damaged part */
+    CHECK_ERR(err, "inflateSync");
+
+    err = inflate(&d_stream, Z_FINISH);
+    if (err != Z_DATA_ERROR) {
+        fprintf(stderr, "inflate should report DATA_ERROR\n");
+        /* Because of incorrect adler32 */
+        exit(1);
+    }
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    err = deflateSetDictionary(&c_stream,
+                (const Bytef*)dictionary, (int)sizeof(dictionary));
+    CHECK_ERR(err, "deflateSetDictionary");
+
+    dictId = c_stream.adler;
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    c_stream.next_in = (z_const unsigned char *)hello;
+    c_stream.avail_in = (uInt)strlen(hello)+1;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+        exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    for (;;) {
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        if (err == Z_NEED_DICT) {
+            if (d_stream.adler != dictId) {
+                fprintf(stderr, "unexpected dictionary");
+                exit(1);
+            }
+            err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+                                       (int)sizeof(dictionary));
+        }
+        CHECK_ERR(err, "inflate with dict");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate with dict\n");
+        exit(1);
+    } else {
+        printf("inflate with dictionary: %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Usage:  example [output.gz  [input.gz]]
+ */
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    Byte *compr, *uncompr;
+    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+    uLong uncomprLen = comprLen;
+    static const char* myVersion = ZLIB_VERSION;
+
+    if (zlibVersion()[0] != myVersion[0]) {
+        fprintf(stderr, "incompatible zlib version\n");
+        exit(1);
+
+    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+        fprintf(stderr, "warning: different zlib version\n");
+    }
+
+    printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
+            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
+    if (isUsingZSTD()) printf("zstd version %s\n", zstdVersion());
+
+    compr    = (Byte*)calloc((uInt)comprLen, 1);
+    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
+    /* compr and uncompr are cleared to avoid reading uninitialized
+     * data and to ensure that uncompr compresses well.
+     */
+    if (compr == Z_NULL || uncompr == Z_NULL) {
+        printf("out of memory\n");
+        exit(1);
+    }
+
+#ifdef Z_SOLO
+    argc = strlen(argv[0]);
+#else
+    test_compress(compr, comprLen, uncompr, uncomprLen);
+
+    if (!isUsingZSTD())
+        test_gzio((argc > 1 ? argv[1] : TESTFILE),
+              uncompr, uncomprLen);
+#endif
+
+    test_deflate(compr, comprLen);
+    test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+    test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    if (!isUsingZSTD()) {
+        test_flush(compr, &comprLen);
+        test_sync(compr, comprLen, uncompr, uncomprLen);
+    }
+    comprLen = uncomprLen;
+
+    test_dict_deflate(compr, comprLen);
+    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    free(compr);
+    free(uncompr);
+
+    return 0;
+}
diff --git a/zlibWrapper/examples/example_original.c b/zlibWrapper/examples/example_original.c
new file mode 100644 (file)
index 0000000..138a699
--- /dev/null
@@ -0,0 +1,601 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-2006, 2011 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+#include <stdio.h>
+
+#ifdef STDC
+#  include <string.h>
+#  include <stdlib.h>
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+#  define TESTFILE "foo-gz"
+#else
+#  define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+    if (err != Z_OK) { \
+        fprintf(stderr, "%s error: %d\n", msg, err); \
+        exit(1); \
+    } \
+}
+
+z_const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_deflate       OF((Byte *compr, uLong comprLen));
+void test_inflate       OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_flush         OF((Byte *compr, uLong *comprLen));
+void test_sync          OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate  OF((Byte *compr, uLong comprLen));
+void test_dict_inflate  OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+int  main               OF((int argc, char *argv[]));
+
+
+#ifdef Z_SOLO
+
+void *myalloc OF((void *, unsigned, unsigned));
+void myfree OF((void *, void *));
+
+void *myalloc(q, n, m)
+    void *q;
+    unsigned n, m;
+{
+    q = Z_NULL;
+    return calloc(n, m);
+}
+
+void myfree(void *q, void *p)
+{
+    q = Z_NULL;
+    free(p);
+}
+
+static alloc_func zalloc = myalloc;
+static free_func zfree = myfree;
+
+#else /* !Z_SOLO */
+
+static alloc_func zalloc = (alloc_func)0;
+static free_func zfree = (free_func)0;
+
+void test_compress      OF((Byte *compr, uLong comprLen,
+                            Byte *uncompr, uLong uncomprLen));
+void test_gzio          OF((const char *fname,
+                            Byte *uncompr, uLong uncomprLen));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    uLong len = (uLong)strlen(hello)+1;
+
+    err = compress(compr, &comprLen, (const Bytef*)hello, len);
+    CHECK_ERR(err, "compress");
+
+    strcpy((char*)uncompr, "garbage");
+
+    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+    CHECK_ERR(err, "uncompress");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad uncompress\n");
+        exit(1);
+    } else {
+        printf("uncompress(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(fname, uncompr, uncomprLen)
+    const char *fname; /* compressed file name */
+    Byte *uncompr;
+    uLong uncomprLen;
+{
+#ifdef NO_GZCOMPRESS
+    fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
+#else
+    int err;
+    int len = (int)strlen(hello)+1;
+    gzFile file;
+    z_off_t pos;
+
+    file = gzopen(fname, "wb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+        exit(1);
+    }
+    gzputc(file, 'h');
+    if (gzputs(file, "ello") != 4) {
+        fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (gzprintf(file, ", %s!", "hello") != 8) {
+        fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+    gzclose(file);
+
+    file = gzopen(fname, "rb");
+    if (file == NULL) {
+        fprintf(stderr, "gzopen error\n");
+        exit(1);
+    }
+    strcpy((char*)uncompr, "garbage");
+
+    if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
+        fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+        exit(1);
+    } else {
+        printf("gzread(): %s\n", (char*)uncompr);
+    }
+
+    pos = gzseek(file, -8L, SEEK_CUR);
+    if (pos != 6 || gztell(file) != pos) {
+        fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+                (long)pos, (long)gztell(file));
+        exit(1);
+    }
+
+    if (gzgetc(file) != ' ') {
+        fprintf(stderr, "gzgetc error\n");
+        exit(1);
+    }
+
+    if (gzungetc(' ', file) != ' ') {
+        fprintf(stderr, "gzungetc error\n");
+        exit(1);
+    }
+
+    gzgets(file, (char*)uncompr, (int)uncomprLen);
+    if (strlen((char*)uncompr) != 7) { /* " hello!" */
+        fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+        exit(1);
+    }
+    if (strcmp((char*)uncompr, hello + 6)) {
+        fprintf(stderr, "bad gzgets after gzseek\n");
+        exit(1);
+    } else {
+        printf("gzgets() after gzseek: %s\n", (char*)uncompr);
+    }
+
+    gzclose(file);
+#endif
+}
+
+#endif /* Z_SOLO */
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    uLong len = (uLong)strlen(hello)+1;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (z_const unsigned char *)hello;
+    c_stream.next_out = compr;
+
+    while (c_stream.total_in != len && c_stream.total_out < comprLen) {
+        c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+        err = deflate(&c_stream, Z_NO_FLUSH);
+        CHECK_ERR(err, "deflate");
+    }
+    /* Finish the stream, still forcing small buffers: */
+    for (;;) {
+        c_stream.avail_out = 1;
+        err = deflate(&c_stream, Z_FINISH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "deflate");
+    }
+
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 0;
+    d_stream.next_out = uncompr;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate\n");
+        exit(1);
+    } else {
+        printf("inflate(): %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_SPEED);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    /* At this point, uncompr is still mostly zeroes, so it should compress
+     * very well:
+     */
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+    if (c_stream.avail_in != 0) {
+        fprintf(stderr, "deflate not greedy\n");
+        exit(1);
+    }
+
+    /* Feed in already compressed data and switch to no compression: */
+    deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+    c_stream.next_in = compr;
+    c_stream.avail_in = (uInt)comprLen/2;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    /* Switch back to compressing mode: */
+    deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+    c_stream.next_in = uncompr;
+    c_stream.avail_in = (uInt)uncomprLen;
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+        exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    for (;;) {
+        d_stream.next_out = uncompr;            /* discard the output */
+        d_stream.avail_out = (uInt)uncomprLen;
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        CHECK_ERR(err, "large inflate");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+        fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+        exit(1);
+    } else {
+        printf("large_inflate(): OK\n");
+    }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+    Byte *compr;
+    uLong *comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+    uInt len = (uInt)strlen(hello)+1;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    c_stream.next_in  = (z_const unsigned char *)hello;
+    c_stream.next_out = compr;
+    c_stream.avail_in = 3;
+    c_stream.avail_out = (uInt)*comprLen;
+    err = deflate(&c_stream, Z_FULL_FLUSH);
+    CHECK_ERR(err, "deflate");
+
+    compr[3]++; /* force an error in first compressed block */
+    c_stream.avail_in = len - 3;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        CHECK_ERR(err, "deflate");
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+
+    *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = 2; /* just read the zlib header */
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    inflate(&d_stream, Z_NO_FLUSH);
+    CHECK_ERR(err, "inflate");
+
+    d_stream.avail_in = (uInt)comprLen-2;   /* read all compressed data */
+    err = inflateSync(&d_stream);           /* but skip the damaged part */
+    CHECK_ERR(err, "inflateSync");
+
+    err = inflate(&d_stream, Z_FINISH);
+    if (err != Z_DATA_ERROR) {
+        fprintf(stderr, "inflate should report DATA_ERROR\n");
+        /* Because of incorrect adler32 */
+        exit(1);
+    }
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+    Byte *compr;
+    uLong comprLen;
+{
+    z_stream c_stream; /* compression stream */
+    int err;
+
+    c_stream.zalloc = zalloc;
+    c_stream.zfree = zfree;
+    c_stream.opaque = (voidpf)0;
+
+    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+    CHECK_ERR(err, "deflateInit");
+
+    err = deflateSetDictionary(&c_stream,
+                (const Bytef*)dictionary, (int)sizeof(dictionary));
+    CHECK_ERR(err, "deflateSetDictionary");
+
+    dictId = c_stream.adler;
+    c_stream.next_out = compr;
+    c_stream.avail_out = (uInt)comprLen;
+
+    c_stream.next_in = (z_const unsigned char *)hello;
+    c_stream.avail_in = (uInt)strlen(hello)+1;
+
+    err = deflate(&c_stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        fprintf(stderr, "deflate should report Z_STREAM_END\n");
+        exit(1);
+    }
+    err = deflateEnd(&c_stream);
+    CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+    Byte *compr, *uncompr;
+    uLong comprLen, uncomprLen;
+{
+    int err;
+    z_stream d_stream; /* decompression stream */
+
+    strcpy((char*)uncompr, "garbage");
+
+    d_stream.zalloc = zalloc;
+    d_stream.zfree = zfree;
+    d_stream.opaque = (voidpf)0;
+
+    d_stream.next_in  = compr;
+    d_stream.avail_in = (uInt)comprLen;
+
+    err = inflateInit(&d_stream);
+    CHECK_ERR(err, "inflateInit");
+
+    d_stream.next_out = uncompr;
+    d_stream.avail_out = (uInt)uncomprLen;
+
+    for (;;) {
+        err = inflate(&d_stream, Z_NO_FLUSH);
+        if (err == Z_STREAM_END) break;
+        if (err == Z_NEED_DICT) {
+            if (d_stream.adler != dictId) {
+                fprintf(stderr, "unexpected dictionary");
+                exit(1);
+            }
+            err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+                                       (int)sizeof(dictionary));
+        }
+        CHECK_ERR(err, "inflate with dict");
+    }
+
+    err = inflateEnd(&d_stream);
+    CHECK_ERR(err, "inflateEnd");
+
+    if (strcmp((char*)uncompr, hello)) {
+        fprintf(stderr, "bad inflate with dict\n");
+        exit(1);
+    } else {
+        printf("inflate with dictionary: %s\n", (char *)uncompr);
+    }
+}
+
+/* ===========================================================================
+ * Usage:  example [output.gz  [input.gz]]
+ */
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+    Byte *compr, *uncompr;
+    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+    uLong uncomprLen = comprLen;
+    static const char* myVersion = ZLIB_VERSION;
+
+    if (zlibVersion()[0] != myVersion[0]) {
+        fprintf(stderr, "incompatible zlib version\n");
+        exit(1);
+
+    } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+        fprintf(stderr, "warning: different zlib version\n");
+    }
+
+    printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
+            ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
+
+    compr    = (Byte*)calloc((uInt)comprLen, 1);
+    uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
+    /* compr and uncompr are cleared to avoid reading uninitialized
+     * data and to ensure that uncompr compresses well.
+     */
+    if (compr == Z_NULL || uncompr == Z_NULL) {
+        printf("out of memory\n");
+        exit(1);
+    }
+
+#ifdef Z_SOLO
+    argc = strlen(argv[0]);
+#else
+    test_compress(compr, comprLen, uncompr, uncomprLen);
+
+    test_gzio((argc > 1 ? argv[1] : TESTFILE),
+              uncompr, uncomprLen);
+#endif
+
+    test_deflate(compr, comprLen);
+    test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+    test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    test_flush(compr, &comprLen);
+    test_sync(compr, comprLen, uncompr, uncomprLen);
+    comprLen = uncomprLen;
+
+    test_dict_deflate(compr, comprLen);
+    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+    free(compr);
+    free(uncompr);
+
+    return 0;
+}
diff --git a/zlibWrapper/zstd_zlibwrapper.c b/zlibWrapper/zstd_zlibwrapper.c
new file mode 100644 (file)
index 0000000..5df1215
--- /dev/null
@@ -0,0 +1,905 @@
+/*
+    zstd_zlibwrapper.c - zstd wrapper for zlib
+    Copyright (C) 2016, Przemyslaw Skibinski.
+
+    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    You can contact the author at :
+    - zstd source repository : https://github.com/Cyan4973/zstd
+*/
+
+#include <stdio.h>           /* fprintf */
+#include <stdlib.h>          /* malloc */
+#include <zlib.h>
+#include "zstd_zlibwrapper.h"
+#include "zstd.h"
+#include "zstd_static.h"      /* ZSTD_MAGICNUMBER */
+#include "zstd_internal.h"    /* MIN */
+#include "zbuff.h"
+
+
+#define Z_INFLATE_SYNC              8
+#define ZWRAP_HEADERSIZE            4
+#define ZSTD_FRAMEHEADERSIZE_MIN    5
+
+#define LOG_WRAPPER(...)  // printf(__VA_ARGS__)
+
+
+#define FINISH_WITH_ERR(msg) { \
+    fprintf(stderr, "ERROR: %s\n", msg); \
+    return Z_MEM_ERROR; \
+}
+
+#define FINISH_WITH_NULL_ERR(msg) { \
+    fprintf(stderr, "ERROR: %s\n", msg); \
+    return NULL; \
+}
+
+#ifndef ZWRAP_USE_ZSTD
+    #define ZWRAP_USE_ZSTD 0
+#endif
+
+static int g_useZSTD = ZWRAP_USE_ZSTD;   /* 0 = don't use ZSTD */
+
+
+
+void useZSTD(int turn_on) { g_useZSTD = turn_on; }
+
+int isUsingZSTD() { return g_useZSTD; }
+
+const char * zstdVersion() { return ZSTD_VERSION_STRING; }
+
+ZEXTERN const char * ZEXPORT z_zlibVersion OF((void)) { return zlibVersion();  }
+
+
+
+/* *** Compression *** */
+
+typedef struct {
+    ZBUFF_CCtx* zbc;
+    size_t bytesLeft;
+    int compressionLevel;
+} ZWRAP_CCtx;
+
+
+ZWRAP_CCtx* ZWRAP_createCCtx()
+{
+    ZWRAP_CCtx* zwc = (ZWRAP_CCtx*)malloc(sizeof(ZWRAP_CCtx));
+    if (zwc==NULL) return NULL;
+    memset(zwc, 0, sizeof(*zwc));
+    zwc->zbc = ZBUFF_createCCtx();
+    return zwc;
+}
+
+
+size_t ZWRAP_freeCCtx(ZWRAP_CCtx* zwc)
+{
+    if (zwc==NULL) return 0;   /* support free on NULL */
+    ZBUFF_freeCCtx(zwc->zbc);
+    free(zwc);
+    return 0;
+}
+
+
+ZEXTERN int ZEXPORT z_deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size))
+{
+    ZWRAP_CCtx* zwc;
+    
+    if (!g_useZSTD) {
+        LOG_WRAPPER("- deflateInit level=%d\n", level);
+        return deflateInit_((strm), (level), version, stream_size);
+    }
+
+    LOG_WRAPPER("- deflateInit level=%d\n", level);
+    zwc = ZWRAP_createCCtx();
+    if (zwc == NULL) return Z_MEM_ERROR;
+
+    { size_t const errorCode = ZBUFF_compressInit(zwc->zbc, level);
+      if (ZSTD_isError(errorCode)) return Z_MEM_ERROR; }
+
+    zwc->compressionLevel = level;
+    strm->opaque = (voidpf) zwc;
+    strm->total_in = 0;
+    strm->total_out = 0;
+    return Z_OK;
+}
+
+
+ZEXTERN int ZEXPORT z_deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size))
+{
+    if (!g_useZSTD)
+        return deflateInit2_(strm, level, method, windowBits, memLevel, strategy, version, stream_size);
+
+    return z_deflateInit_ (strm, level, version, stream_size);
+}
+
+
+ZEXTERN int ZEXPORT z_deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength))
+{
+    if (!g_useZSTD)
+        return deflateSetDictionary(strm, dictionary, dictLength);
+
+    {   ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->opaque;
+        LOG_WRAPPER("- deflateSetDictionary level=%d\n", (int)strm->data_type);
+        { size_t const errorCode = ZBUFF_compressInitDictionary(zwc->zbc, dictionary, dictLength, zwc->compressionLevel);
+          if (ZSTD_isError(errorCode)) return Z_MEM_ERROR; }
+    }
+    
+    return Z_OK;
+}
+
+
+ZEXTERN int ZEXPORT z_deflate OF((z_streamp strm, int flush))
+{
+    ZWRAP_CCtx* zwc;
+
+    if (!g_useZSTD) {
+        int res = deflate(strm, flush);
+        LOG_WRAPPER("- avail_in=%d total_in=%d total_out=%d\n", (int)strm->avail_in, (int)strm->total_in, (int)strm->total_out);
+        return res;
+    }
+
+    zwc = (ZWRAP_CCtx*) strm->opaque;
+
+    LOG_WRAPPER("deflate 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);
+    if (strm->avail_in > 0) {
+        size_t dstCapacity = strm->avail_out;
+        size_t srcSize = strm->avail_in;
+        size_t const errorCode = ZBUFF_compressContinue(zwc->zbc, strm->next_out, &dstCapacity, strm->next_in, &srcSize);
+        LOG_WRAPPER("ZBUFF_compressContinue srcSize=%d dstCapacity=%d\n", (int)srcSize, (int)dstCapacity);
+        if (ZSTD_isError(errorCode)) return Z_MEM_ERROR;
+        strm->next_out += dstCapacity;
+        strm->total_out += dstCapacity;
+        strm->avail_out -= dstCapacity;
+        strm->total_in += srcSize;
+        strm->next_in += srcSize;
+        strm->avail_in -= srcSize;
+    }
+
+    if (flush == Z_FULL_FLUSH) FINISH_WITH_ERR("Z_FULL_FLUSH is not supported!");
+
+    if (flush == Z_FINISH || flush == Z_FULL_FLUSH) {
+        size_t bytesLeft;
+        size_t dstCapacity = strm->avail_out;
+        if (zwc->bytesLeft) {
+            bytesLeft = ZBUFF_compressFlush(zwc->zbc, strm->next_out, &dstCapacity);
+            LOG_WRAPPER("ZBUFF_compressFlush avail_out=%d dstCapacity=%d bytesLeft=%d\n", (int)strm->avail_out, (int)dstCapacity, (int)bytesLeft);
+        } else {
+            bytesLeft = ZBUFF_compressEnd(zwc->zbc, strm->next_out, &dstCapacity);
+            LOG_WRAPPER("ZBUFF_compressEnd dstCapacity=%d bytesLeft=%d\n", (int)dstCapacity, (int)bytesLeft);
+      //      { size_t const errorCode = ZBUFF_compressInit(zwc->zbc, 1);
+      //        if (ZSTD_isError(errorCode)) return Z_MEM_ERROR; }
+        }
+        if (ZSTD_isError(bytesLeft)) return Z_MEM_ERROR;
+        strm->next_out += dstCapacity;
+        strm->total_out += dstCapacity;
+        strm->avail_out -= dstCapacity;
+        if (flush == Z_FINISH && bytesLeft == 0) return Z_STREAM_END;
+        zwc->bytesLeft = bytesLeft;
+    }
+    return Z_OK;
+}
+
+
+ZEXTERN int ZEXPORT z_deflateEnd OF((z_streamp strm)) 
+{
+    if (!g_useZSTD) {
+        LOG_WRAPPER("- deflateEnd\n");
+        return deflateEnd(strm);
+    }
+    LOG_WRAPPER("- deflateEnd total_in=%d total_out=%d\n", (int)(strm->total_in), (int)(strm->total_out));
+    {   ZWRAP_CCtx* zwc = (ZWRAP_CCtx*) strm->opaque;
+        size_t const errorCode = ZWRAP_freeCCtx(zwc);
+        if (ZSTD_isError(errorCode)) return Z_MEM_ERROR;
+    }
+    return Z_OK;
+}
+
+
+ZEXTERN uLong ZEXPORT z_deflateBound OF((z_streamp strm,
+                                       uLong sourceLen))
+{
+    if (!g_useZSTD)
+        return deflateBound(strm, sourceLen);
+
+    return ZSTD_compressBound(sourceLen);
+}
+
+
+ZEXTERN int ZEXPORT z_deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy))
+{
+    if (!g_useZSTD) {
+        LOG_WRAPPER("- deflateParams level=%d strategy=%d\n", level, strategy);
+        return deflateParams(strm, level, strategy);
+    }
+
+    return Z_OK;
+}
+
+
+
+
+
+/* *** Decompression *** */
+
+typedef struct {
+    ZBUFF_DCtx* zbd;
+    char headerBuf[ZSTD_FRAMEHEADERSIZE_MIN];
+    int errorCount;
+    int requiredHeaderSize;
+    
+    /* zlib params */
+    int stream_size;
+    char *version;
+    int windowBits;
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */ 
+} ZWRAP_DCtx;
+
+
+ZWRAP_DCtx* ZWRAP_createDCtx(void)
+{
+    ZWRAP_DCtx* zwd = (ZWRAP_DCtx*)malloc(sizeof(ZWRAP_DCtx));
+    if (zwd==NULL) return NULL;
+    memset(zwd, 0, sizeof(*zwd));
+    return zwd;
+}
+
+
+size_t ZWRAP_freeDCtx(ZWRAP_DCtx* zwd)
+{
+    if (zwd==NULL) return 0;   /* support free on null */
+    if (zwd->version) free(zwd->version);
+    if (zwd->zbd) ZBUFF_freeDCtx(zwd->zbd);
+    free(zwd);
+    return 0;
+}
+
+
+ZEXTERN int ZEXPORT z_inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size))
+{
+    ZWRAP_DCtx* zwd = ZWRAP_createDCtx();
+    LOG_WRAPPER("- inflateInit\n");
+    if (zwd == NULL) return Z_MEM_ERROR;
+
+    zwd->stream_size = stream_size;
+    zwd->version = strdup(version);
+    zwd->zalloc = strm->zalloc;
+    zwd->zfree = strm->zfree;
+    zwd->opaque = strm->opaque;
+    zwd->requiredHeaderSize = ZWRAP_HEADERSIZE;
+
+    strm->state = (struct internal_state*) zwd;
+    strm->total_in = 0;
+    strm->total_out = 0;
+    strm->reserved = 1; /* mark as unknown steam */
+
+    return Z_OK;
+}
+
+
+ZEXTERN int ZEXPORT z_inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size))
+{
+    int ret = z_inflateInit_ (strm, version, stream_size);
+    if (ret == Z_OK) {
+        ZWRAP_DCtx* zwd = (ZWRAP_DCtx*)strm->state;
+        zwd->windowBits = windowBits;
+    }
+    return ret;
+}
+
+
+
+
+ZEXTERN int ZEXPORT z_inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength))
+{
+    if (!strm->reserved)
+        return inflateSetDictionary(strm, dictionary, dictLength);
+
+    LOG_WRAPPER("- inflateSetDictionary\n");
+    {   ZWRAP_DCtx* zwd = (ZWRAP_DCtx*) strm->state;
+        size_t errorCode = ZBUFF_decompressInitDictionary(zwd->zbd, dictionary, dictLength);
+        if (ZSTD_isError(errorCode)) return Z_MEM_ERROR; 
+        
+        if (strm->total_in == ZSTD_frameHeaderSize_min) {
+            size_t dstCapacity = 0;
+            size_t srcSize = strm->total_in;
+            errorCode = ZBUFF_decompressContinue(zwd->zbd, strm->next_out, &dstCapacity, zwd->headerBuf, &srcSize);
+            LOG_WRAPPER("ZBUFF_decompressContinue3 errorCode=%d srcSize=%d dstCapacity=%d\n", (int)errorCode, (int)srcSize, (int)dstCapacity);
+            if (dstCapacity > 0 || ZSTD_isError(errorCode)) {
+                LOG_WRAPPER("ERROR: ZBUFF_decompressContinue %s\n", ZSTD_getErrorName(errorCode));
+                return Z_MEM_ERROR;
+            }
+        }
+    }
+
+    return Z_OK;
+}
+
+
+ZEXTERN int ZEXPORT z_inflate OF((z_streamp strm, int flush)) 
+{
+    if (!strm->reserved)
+        return inflate(strm, flush);
+
+    if (strm->avail_in > 0) {
+        size_t errorCode, dstCapacity, srcSize;
+        ZWRAP_DCtx* zwd = (ZWRAP_DCtx*) strm->state;
+        LOG_WRAPPER("inflate avail_in=%d avail_out=%d total_in=%d total_out=%d\n", (int)strm->avail_in, (int)strm->avail_out, (int)strm->total_in, (int)strm->total_out);
+        while (strm->total_in < ZSTD_FRAMEHEADERSIZE_MIN)
+        {
+            srcSize = MIN(strm->avail_in, zwd->requiredHeaderSize - strm->total_in);
+            memcpy(zwd->headerBuf+strm->total_in, strm->next_in, srcSize);
+            strm->total_in += srcSize;
+            strm->next_in += srcSize;
+            strm->avail_in -= srcSize;
+            if (strm->total_in < zwd->requiredHeaderSize) return Z_OK;
+
+            if (MEM_readLE32(zwd->headerBuf) != ZSTD_MAGICNUMBER) {
+                z_stream strm2;
+                strm2.next_in = strm->next_in;
+                strm2.avail_in = strm->avail_in;
+                strm2.next_out = strm->next_out;
+                strm2.avail_out = strm->avail_out;
+
+                if (zwd->windowBits)
+                    errorCode = inflateInit2_(strm, zwd->windowBits, zwd->version, zwd->stream_size);
+                else
+                    errorCode = inflateInit_(strm, zwd->version, zwd->stream_size);
+                LOG_WRAPPER("ZLIB inflateInit errorCode=%d\n", (int)errorCode);
+                if (errorCode != Z_OK) return errorCode;
+
+                /* inflate header */
+                strm->next_in = (unsigned char*)zwd->headerBuf;
+                strm->avail_in = ZWRAP_HEADERSIZE;
+                strm->avail_out = 0;
+                errorCode = inflate(strm, Z_NO_FLUSH);
+                LOG_WRAPPER("ZLIB inflate errorCode=%d strm->avail_in=%d\n", (int)errorCode, (int)strm->avail_in);
+                if (errorCode != Z_OK) return errorCode;
+                if (strm->avail_in > 0) return Z_MEM_ERROR;
+                
+                strm->next_in = strm2.next_in;
+                strm->avail_in = strm2.avail_in;
+                strm->next_out = strm2.next_out;
+                strm->avail_out = strm2.avail_out;
+                strm->reserved = 0; /* mark as zlib stream */
+                if (flush == Z_INFLATE_SYNC) return inflateSync(strm);
+                return inflate(strm, flush);
+            }
+
+            if (zwd->requiredHeaderSize < ZSTD_FRAMEHEADERSIZE_MIN) {
+                zwd->requiredHeaderSize = ZSTD_FRAMEHEADERSIZE_MIN;
+                continue;
+            }
+
+            zwd->zbd = ZBUFF_createDCtx();
+            { size_t const errorCode = ZBUFF_decompressInit(zwd->zbd);
+              if (ZSTD_isError(errorCode)) return Z_MEM_ERROR; }
+
+            srcSize = ZSTD_FRAMEHEADERSIZE_MIN;
+            dstCapacity = 0;
+            errorCode = ZBUFF_decompressContinue(zwd->zbd, strm->next_out, &dstCapacity, zwd->headerBuf, &srcSize);
+            LOG_WRAPPER("ZBUFF_decompressContinue1 errorCode=%d srcSize=%d dstCapacity=%d\n", (int)errorCode, (int)srcSize, (int)dstCapacity);
+            if (ZSTD_isError(errorCode)) {
+                LOG_WRAPPER("ERROR: ZBUFF_decompressContinue %s\n", ZSTD_getErrorName(errorCode));
+                return Z_MEM_ERROR;
+            }
+            if (strm->avail_in == 0) return Z_OK;
+            break;
+        }
+
+        srcSize = strm->avail_in;
+        dstCapacity = strm->avail_out;
+        errorCode = ZBUFF_decompressContinue(zwd->zbd, strm->next_out, &dstCapacity, strm->next_in, &srcSize);
+        LOG_WRAPPER("ZBUFF_decompressContinue2 errorCode=%d srcSize=%d dstCapacity=%d\n", (int)errorCode, (int)srcSize, (int)dstCapacity);
+        if (ZSTD_isError(errorCode)) {
+            LOG_WRAPPER("ERROR: ZBUFF_decompressContinue %s\n", ZSTD_getErrorName(errorCode));
+            zwd->errorCount++;
+            return (zwd->errorCount<=1) ? Z_NEED_DICT : Z_MEM_ERROR;
+        }
+        strm->next_out += dstCapacity;
+        strm->total_out += dstCapacity;
+        strm->avail_out -= dstCapacity;
+        strm->total_in += srcSize;
+        strm->next_in += srcSize;
+        strm->avail_in -= srcSize;
+        if (errorCode == 0) return Z_STREAM_END;
+    }
+    return Z_OK;
+}
+
+
+ZEXTERN int ZEXPORT z_inflateEnd OF((z_streamp strm))
+{
+    int ret = Z_OK;
+    if (!strm->reserved)
+        ret = inflateEnd(strm);
+    LOG_WRAPPER("- inflateEnd total_in=%d total_out=%d\n", (int)(strm->total_in), (int)(strm->total_out));
+    {   ZWRAP_DCtx* zwd = (ZWRAP_DCtx*) strm->state;
+        size_t const errorCode = ZWRAP_freeDCtx(zwd);
+        if (ZSTD_isError(errorCode)) return Z_MEM_ERROR;
+    }
+    return ret;
+}
+
+
+ZEXTERN int ZEXPORT z_inflateSync OF((z_streamp strm))
+{
+    return z_inflate(strm, Z_INFLATE_SYNC);
+}
+
+
+
+
+/* Advanced compression functions */
+ZEXTERN int ZEXPORT z_deflateCopy OF((z_streamp dest,
+                                    z_streamp source))
+{
+    if (!g_useZSTD)
+        return deflateCopy(dest, source);
+    FINISH_WITH_ERR("deflateCopy is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_deflateReset OF((z_streamp strm))
+{
+    if (!g_useZSTD)
+        return deflateReset(strm);
+    FINISH_WITH_ERR("deflateReset is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain))
+{
+    if (!g_useZSTD)
+        return deflateTune(strm, good_length, max_lazy, nice_length, max_chain);
+    FINISH_WITH_ERR("deflateTune is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits))
+{
+    if (!g_useZSTD)
+        return deflatePending(strm, pending, bits);
+    FINISH_WITH_ERR("deflatePending is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value))
+{
+    if (!g_useZSTD)
+        return deflatePrime(strm, bits, value);
+    FINISH_WITH_ERR("deflatePrime is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head))
+{
+    if (!g_useZSTD)
+        return deflateSetHeader(strm, head);
+    FINISH_WITH_ERR("deflateSetHeader is not supported!");
+}
+
+
+
+
+/* Advanced compression functions */
+ZEXTERN int ZEXPORT z_inflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength))
+{
+    if (!strm->reserved)
+        return inflateGetDictionary(strm, dictionary, dictLength);
+    FINISH_WITH_ERR("inflateGetDictionary is not supported!");
+}
+
+
+
+ZEXTERN int ZEXPORT z_inflateCopy OF((z_streamp dest,
+                                    z_streamp source))
+{
+    if (!g_useZSTD)
+        return inflateCopy(dest, source);
+    FINISH_WITH_ERR("inflateCopy is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_inflateReset OF((z_streamp strm))
+{
+    if (!strm->reserved)
+        return inflateReset(strm);
+    FINISH_WITH_ERR("inflateReset is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_inflateReset2 OF((z_streamp strm,
+                                      int windowBits))
+{
+    if (!strm->reserved)
+        return inflateReset2(strm, windowBits);
+    FINISH_WITH_ERR("inflateReset2 is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value))
+{
+    if (!strm->reserved)
+        return inflatePrime(strm, bits, value);
+    FINISH_WITH_ERR("inflatePrime is not supported!");
+}
+
+
+ZEXTERN long ZEXPORT z_inflateMark OF((z_streamp strm))
+{
+    if (!strm->reserved)
+        return inflateMark(strm);
+    FINISH_WITH_ERR("inflateMark is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head))
+{
+    if (!strm->reserved)
+        return inflateGetHeader(strm, head);
+    FINISH_WITH_ERR("inflateGetHeader is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size))
+{
+    if (!strm->reserved)
+        return inflateBackInit_(strm, windowBits, window, version, stream_size);
+    FINISH_WITH_ERR("inflateBackInit is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc))
+{
+    if (!strm->reserved)
+        return inflateBack(strm, in, in_desc, out, out_desc);
+    FINISH_WITH_ERR("inflateBack is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_inflateBackEnd OF((z_streamp strm))
+{
+    if (!strm->reserved)
+        return inflateBackEnd(strm);
+    FINISH_WITH_ERR("inflateBackEnd is not supported!");
+}
+
+
+ZEXTERN uLong ZEXPORT z_zlibCompileFlags OF((void)) { return zlibCompileFlags(); };
+
+
+
+                        /* utility functions */
+#ifndef Z_SOLO
+
+ZEXTERN int ZEXPORT z_compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen))
+{
+    if (!g_useZSTD)
+        return compress(dest, destLen, source, sourceLen);
+
+    size_t dstCapacity = *destLen; 
+    LOG_WRAPPER("z_compress sourceLen=%d dstCapacity=%d\n", (int)sourceLen, (int)dstCapacity);
+    { size_t const errorCode = ZSTD_compress(dest, dstCapacity, source, sourceLen, -1);
+      if (ZSTD_isError(errorCode)) return Z_MEM_ERROR;
+      *destLen = errorCode;
+    }
+    return Z_OK;
+}
+
+
+ZEXTERN int ZEXPORT z_compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level))
+{
+    if (!g_useZSTD)
+        return compress2(dest, destLen, source, sourceLen, level);
+        
+    size_t dstCapacity = *destLen; 
+    { size_t const errorCode = ZSTD_compress(dest, dstCapacity, source, sourceLen, level);
+      if (ZSTD_isError(errorCode)) return Z_MEM_ERROR;
+      *destLen = errorCode;
+    }
+    return Z_OK;
+}
+
+
+ZEXTERN uLong ZEXPORT z_compressBound OF((uLong sourceLen))
+{
+    if (!g_useZSTD)
+        return compressBound(sourceLen);
+
+    return ZSTD_compressBound(sourceLen);
+}
+
+
+ZEXTERN int ZEXPORT z_uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen))
+{
+    if (sourceLen < 4 || MEM_readLE32(source) != ZSTD_MAGICNUMBER)
+//    if (!g_useZSTD)
+        return uncompress(dest, destLen, source, sourceLen);
+
+    size_t dstCapacity = *destLen; 
+    { size_t const errorCode = ZSTD_decompress(dest, dstCapacity, source, sourceLen);
+      if (ZSTD_isError(errorCode)) return Z_MEM_ERROR;
+      *destLen = errorCode;
+     }
+    return Z_OK;
+}
+
+
+
+                        /* gzip file access functions */
+ZEXTERN gzFile ZEXPORT z_gzopen OF((const char *path, const char *mode))
+{
+    if (!g_useZSTD)
+        return gzopen(path, mode);
+    FINISH_WITH_NULL_ERR("gzopen is not supported!");
+}
+
+
+ZEXTERN gzFile ZEXPORT z_gzdopen OF((int fd, const char *mode))
+{
+    if (!g_useZSTD)
+        return gzdopen(fd, mode);
+    FINISH_WITH_NULL_ERR("gzdopen is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzbuffer OF((gzFile file, unsigned size))
+{
+    if (!g_useZSTD)
+        return gzbuffer(file, size);
+    FINISH_WITH_ERR("gzbuffer is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzsetparams OF((gzFile file, int level, int strategy))
+{
+    if (!g_useZSTD)
+        return gzsetparams(file, level, strategy);
+    FINISH_WITH_ERR("gzsetparams is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzread OF((gzFile file, voidp buf, unsigned len))
+{
+    if (!g_useZSTD)
+        return gzread(file, buf, len);
+    FINISH_WITH_ERR("gzread is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len))
+{
+    if (!g_useZSTD)
+        return gzwrite(file, buf, len);
+    FINISH_WITH_ERR("gzwrite is not supported!");
+}
+
+
+ZEXTERN int ZEXPORTVA z_gzprintf Z_ARG((gzFile file, const char *format, ...))
+{
+    if (!g_useZSTD) {
+        int ret;
+        char buf[1024];
+        va_list args;
+        va_start (args, format);
+        ret = vsprintf (buf, format, args);
+        va_end (args);
+
+        ret = gzprintf(file, buf);
+      //  printf("gzprintf ret=%d\n", ret);
+        return ret;
+    }
+    FINISH_WITH_ERR("gzprintf is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzputs OF((gzFile file, const char *s))
+{
+    if (!g_useZSTD)
+        return gzputs(file, s);
+    FINISH_WITH_ERR("gzputs is not supported!");
+}
+
+
+ZEXTERN char * ZEXPORT z_gzgets OF((gzFile file, char *buf, int len))
+{
+    if (!g_useZSTD)
+        return gzgets(file, buf, len);
+    FINISH_WITH_NULL_ERR("gzgets is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzputc OF((gzFile file, int c))
+{
+    if (!g_useZSTD)
+        return gzputc(file, c);
+    FINISH_WITH_ERR("gzputc is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzgetc OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzgetc(file);
+    FINISH_WITH_ERR("gzgetc is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzungetc OF((int c, gzFile file))
+{
+    if (!g_useZSTD)
+        return gzungetc(c, file);
+    FINISH_WITH_ERR("gzungetc is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzflush OF((gzFile file, int flush))
+{
+    if (!g_useZSTD)
+        return gzflush(file, flush);
+    FINISH_WITH_ERR("gzflush is not supported!");
+}
+
+
+ZEXTERN z_off_t ZEXPORT z_gzseek OF((gzFile file, z_off_t offset, int whence))
+{
+    if (!g_useZSTD)
+        return gzseek(file, offset, whence);
+    FINISH_WITH_ERR("gzseek is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT    z_gzrewind OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzrewind(file);
+    FINISH_WITH_ERR("gzrewind is not supported!");
+}
+
+
+ZEXTERN z_off_t ZEXPORT    z_gztell OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gztell(file);
+    FINISH_WITH_ERR("gztell is not supported!");
+}
+
+
+ZEXTERN z_off_t ZEXPORT z_gzoffset OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzoffset(file);
+    FINISH_WITH_ERR("gzoffset is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzeof OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzeof(file);
+    FINISH_WITH_ERR("gzeof is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzdirect OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzdirect(file);
+    FINISH_WITH_ERR("gzdirect is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT    z_gzclose OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzclose(file);
+    FINISH_WITH_ERR("gzclose is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzclose_r OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzclose_r(file);
+    FINISH_WITH_ERR("gzclose_r is not supported!");
+}
+
+
+ZEXTERN int ZEXPORT z_gzclose_w OF((gzFile file))
+{
+    if (!g_useZSTD)
+        return gzclose_w(file);
+    FINISH_WITH_ERR("gzclose_w is not supported!");
+}
+
+
+ZEXTERN const char * ZEXPORT z_gzerror OF((gzFile file, int *errnum))
+{
+    if (!g_useZSTD)
+        return gzerror(file, errnum);
+    FINISH_WITH_NULL_ERR("gzerror is not supported!");
+}
+
+
+ZEXTERN void ZEXPORT z_gzclearerr OF((gzFile file))
+{
+    if (!g_useZSTD)
+        gzclearerr(file);
+}
+
+
+#endif /* !Z_SOLO */
+
+
+                        /* checksum functions */
+
+ZEXTERN uLong ZEXPORT z_adler32 OF((uLong adler, const Bytef *buf, uInt len))
+{
+    return adler32(adler, buf, len);
+}
+
+ZEXTERN uLong ZEXPORT z_crc32   OF((uLong crc, const Bytef *buf, uInt len))
+{
+    return crc32(crc, buf, len);
+}
diff --git a/zlibWrapper/zstd_zlibwrapper.h b/zlibWrapper/zstd_zlibwrapper.h
new file mode 100644 (file)
index 0000000..c9039dd
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    zstd_zlibwrapper.h - zstd wrapper for zlib
+    Copyright (C) 2016, Przemyslaw Skibinski.
+
+    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are
+    met:
+    * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+    copyright notice, this list of conditions and the following disclaimer
+    in the documentation and/or other materials provided with the
+    distribution.
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+    You can contact the author at :
+    - zstd source repository : https://github.com/Cyan4973/zstd
+*/
+
+#ifndef ZSTD_ZLIBWRAPPER_H
+#define ZSTD_ZLIBWRAPPER_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+#define Z_PREFIX
+#include <zlib.h>
+
+
+void useZSTD(int turn_on);
+int isUsingZSTD();
+const char * zstdVersion();
+
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* ZSTD_ZLIBWRAPPER_H */