From 4dbf7f4a3bc422dfcbea73d7d2dea83db2a748b1 Mon Sep 17 00:00:00 2001 From: inikep Date: Wed, 11 May 2016 14:11:00 +0200 Subject: [PATCH 1/5] dynamic memory allocation in UTIL_createFileList --- programs/bench.c | 3 +- programs/util.h | 118 +++++++++++++++++++++++++++------------------ programs/zstdcli.c | 8 +-- 3 files changed, 74 insertions(+), 55 deletions(-) diff --git a/programs/bench.c b/programs/bench.c index d09e2e39..bc77fe05 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -49,7 +49,6 @@ #define TIMELOOP_MICROSEC 1*1000000ULL /* 1 second */ #define ACTIVEPERIOD_MICROSEC 70*1000000ULL /* 70 seconds */ #define COOLPERIOD_SEC 10 -#define MAX_LIST_SIZE (64*1024) #define KB *(1 <<10) #define MB *(1 <<20) @@ -514,7 +513,7 @@ int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles, char* buf; const char** filenameTable; unsigned i; - nbFiles = UTIL_createFileList(fileNamesTable, nbFiles, MAX_LIST_SIZE, &filenameTable, &buf); + nbFiles = UTIL_createFileList(fileNamesTable, nbFiles, &filenameTable, &buf); if (filenameTable) { for (i=0; i /* _POSIX_C_SOURCE, malloc */ +#include /* features.h with _POSIX_C_SOURCE, malloc */ #include /* fprintf */ #include /* stat */ #include /* stat */ #include "mem.h" /* U32, U64 */ +/* ************************************* +* Constants +***************************************/ +#define LIST_SIZE_INCREASE (8*1024) + + /*-**************************************** * Compiler specifics ******************************************/ @@ -205,15 +211,13 @@ UTIL_STATIC U32 UTIL_isDirectory(const char* infilename) #ifdef _WIN32 # define UTIL_HAS_CREATEFILELIST -UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, char* bufEnd) +UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd) { char path[MAX_PATH]; int pathLength, nbFiles = 0; WIN32_FIND_DATA cFile; HANDLE hFile; - if (*bufStart >= bufEnd) return 0; - pathLength = snprintf(path, MAX_PATH, "%s\\*", dirName); if (pathLength < 0 || pathLength >= MAX_PATH) { fprintf(stderr, "Path length has got too long.\n"); @@ -226,30 +230,34 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, char* return 0; } - while (*bufStart < bufEnd) { + do { + pathLength = snprintf(path, MAX_PATH, "%s\\%s", dirName, cFile.cFileName); + if (pathLength < 0 || pathLength >= MAX_PATH) { + fprintf(stderr, "Path length has got too long.\n"); + continue; + } if (cFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (strcmp (cFile.cFileName, "..") == 0 || - strcmp (cFile.cFileName, ".") == 0) goto next; - pathLength = snprintf(path, MAX_PATH, "%s\\%s", dirName, cFile.cFileName); - if (pathLength < 0 || pathLength >= MAX_PATH) { - fprintf(stderr, "Path length has got too long.\n"); - goto next; - } + strcmp (cFile.cFileName, ".") == 0) continue; // printf ("[%s]\n", path); - nbFiles += UTIL_prepareFileList(path, bufStart, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */ + nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */ + if (*bufStart == NULL) { FindClose(hFile); return 0; } } else if ((cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)) { - pathLength = snprintf(*bufStart, bufEnd - *bufStart, "%s\\%s", dirName, cFile.cFileName); - if (pathLength < 0) break; - *bufStart += pathLength + 1; - if (*bufStart >= bufEnd) break; - nbFiles++; + if (*bufStart + *pos + pathLength >= *bufEnd) { + ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE; + *bufStart = (char*)realloc(*bufStart, newListSize); + *bufEnd = *bufStart + newListSize; + if (*bufStart == NULL) { FindClose(hFile); return 0; } + } + if (*bufStart + *pos + pathLength < *bufEnd) { + strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos)); + *pos += pathLength + 1; + nbFiles++; + } // printf ("%s\\%s nbFiles=%d left=%d\n", dirName, cFile.cFileName, nbFiles, (int)(bufEnd - *bufStart)); } - -next: - if (!FindNextFile(hFile, &cFile)) break; - } + } while (FindNextFile(hFile, &cFile)); FindClose(hFile); return nbFiles; @@ -261,21 +269,19 @@ next: # include /* PATH_MAX */ # include -UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, char* bufEnd) +UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd) { DIR *dir; struct dirent *entry; char path[PATH_MAX]; int pathLength, nbFiles = 0; - if (*bufStart >= bufEnd) return 0; - if (!(dir = opendir(dirName))) { fprintf(stderr, "Cannot open directory '%s': %s\n", dirName, strerror(errno)); return 0; } - while ((entry = readdir(dir)) && (*bufStart < bufEnd)) { + while (entry = readdir(dir)) { if (strcmp (entry->d_name, "..") == 0 || strcmp (entry->d_name, ".") == 0) continue; pathLength = snprintf(path, PATH_MAX, "%s/%s", dirName, entry->d_name); @@ -285,13 +291,20 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, char* } if (UTIL_isDirectory(path)) { // printf ("[%s]\n", path); - nbFiles += UTIL_prepareFileList(path, bufStart, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */ + nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd); /* Recursively call "UTIL_prepareFileList" with the new path. */ + if (*bufStart == NULL) { closedir(dir); return 0; } } else { - pathLength = snprintf(*bufStart, bufEnd - *bufStart, "%s/%s", dirName, entry->d_name); - if (pathLength < 0) break; - *bufStart += pathLength + 1; - if (*bufStart >= bufEnd) break; - nbFiles++; + if (*bufStart + *pos + pathLength >= *bufEnd) { + ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE; + *bufStart = (char*)realloc(*bufStart, newListSize); + *bufEnd = *bufStart + newListSize; + if (*bufStart == NULL) { closedir(dir); return 0; } + } + if (*bufStart + *pos + pathLength < *bufEnd) { + strncpy(*bufStart + *pos, path, *bufEnd - (*bufStart + *pos)); + *pos += pathLength + 1; + nbFiles++; + } // printf ("%s/%s nbFiles=%d left=%d\n", dirName, entry->d_name, nbFiles, (int)(bufEnd - *bufStart)); } } @@ -302,36 +315,47 @@ UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, char* #else -UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, char* bufEnd) +UTIL_STATIC int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd) { - (void)bufStart; (void)bufEnd; - fprintf(stderr, "Directory %s ignored (zstd compiled without _POSIX_C_SOURCE)\n", dirName); + (void)bufStart; (void)bufEnd; (void)pos; + fprintf(stderr, "Directory %s ignored (zstd compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName); return 0; } #endif // #ifdef _WIN32 -UTIL_STATIC int UTIL_createFileList(const char **inputNames, unsigned nbNames, unsigned maxListSize, const char*** filenameTable, char** allocatedBuffer) +UTIL_STATIC int UTIL_createFileList(const char **inputNames, unsigned nbNames, const char*** filenameTable, char** allocatedBuffer) { + size_t pos; unsigned i, nbFiles = 0; - char *pbuf, *bufend, *buf; + char *bufend, *buf; - buf = (char*)malloc(maxListSize); + buf = (char*)malloc(LIST_SIZE_INCREASE); if (!buf) { *filenameTable = NULL; return 0; } - bufend = buf + maxListSize; + bufend = buf + LIST_SIZE_INCREASE; - for (i=0, pbuf = buf; i= bufend) break; - strncpy(pbuf, inputNames[i], bufend - pbuf); - pbuf += len + 1; - nbFiles++; + if (buf + pos + len >= bufend) { + ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE; + buf = (char*)realloc(buf, newListSize); + bufend = buf + newListSize; + if (!buf) { *filenameTable = NULL; return 0; } + } + if (buf + pos + len < bufend) { + strncpy(buf + pos, inputNames[i], bufend - (buf + pos)); + pos += len + 1; + nbFiles++; + } } else - nbFiles += UTIL_prepareFileList(inputNames[i], &pbuf, bufend); + { + nbFiles += UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend); + if (buf == NULL) { *filenameTable = NULL; return 0; } + } } { const char** fileTable = (const char**)malloc((nbFiles+1) * sizeof(const char*)); @@ -340,10 +364,10 @@ UTIL_STATIC int UTIL_createFileList(const char **inputNames, unsigned nbNames, u if (nbFiles == 0) fileTable[0] = buf; - for (i=0, pbuf = buf; i on unix */ - - /*-************************************ * Includes **************************************/ @@ -50,6 +44,7 @@ #endif + /*-************************************ * OS-specific Includes **************************************/ @@ -59,6 +54,7 @@ # define SET_BINARY_MODE(file) _setmode(_fileno(file), _O_BINARY) # define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream)) #else + extern int fileno(FILE *stream); /* triggers fileno() within on POSIX */ # include /* isatty */ # define SET_BINARY_MODE(file) # define IS_CONSOLE(stdStream) isatty(fileno(stdStream)) From 3eabe9b4746e3ff6469a6dd1583814b6f49ef978 Mon Sep 17 00:00:00 2001 From: inikep Date: Thu, 12 May 2016 17:15:41 +0200 Subject: [PATCH 2/5] added zlibWrapper - zstd wrapper for zlib --- programs/util.h | 2 +- zlibWrapper/.gitignore | 26 + zlibWrapper/Makefile | 54 ++ zlibWrapper/README.md | 104 +++ zlibWrapper/examples/example.c | 607 ++++++++++++++++ zlibWrapper/examples/example_original.c | 601 ++++++++++++++++ zlibWrapper/zstd_zlibwrapper.c | 905 ++++++++++++++++++++++++ zlibWrapper/zstd_zlibwrapper.h | 53 ++ 8 files changed, 2351 insertions(+), 1 deletion(-) create mode 100644 zlibWrapper/.gitignore create mode 100644 zlibWrapper/Makefile create mode 100644 zlibWrapper/README.md create mode 100644 zlibWrapper/examples/example.c create mode 100644 zlibWrapper/examples/example_original.c create mode 100644 zlibWrapper/zstd_zlibwrapper.c create mode 100644 zlibWrapper/zstd_zlibwrapper.h diff --git a/programs/util.h b/programs/util.h index 76273412..d791a2c7 100644 --- a/programs/util.h +++ b/programs/util.h @@ -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 index 00000000..56473513 --- /dev/null +++ b/zlibWrapper/.gitignore @@ -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 index 00000000..fd45ee6d --- /dev/null +++ b/zlibWrapper/Makefile @@ -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 index 00000000..5572e3ec --- /dev/null +++ b/zlibWrapper/README.md @@ -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 index 00000000..fe6c80ac --- /dev/null +++ b/zlibWrapper/examples/example.c @@ -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 + +#ifdef STDC +# include +# include +#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 index 00000000..138a699b --- /dev/null +++ b/zlibWrapper/examples/example_original.c @@ -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 + +#ifdef STDC +# include +# include +#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 index 00000000..5df1215e --- /dev/null +++ b/zlibWrapper/zstd_zlibwrapper.c @@ -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 /* fprintf */ +#include /* malloc */ +#include +#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 index 00000000..c9039ddb --- /dev/null +++ b/zlibWrapper/zstd_zlibwrapper.h @@ -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 + + +void useZSTD(int turn_on); +int isUsingZSTD(); +const char * zstdVersion(); + + +#if defined (__cplusplus) +} +#endif + +#endif /* ZSTD_ZLIBWRAPPER_H */ From b5e6870bb5c8f13843eda2b171f53f11eb262e8f Mon Sep 17 00:00:00 2001 From: inikep Date: Thu, 12 May 2016 17:28:57 +0200 Subject: [PATCH 3/5] updated zlibWrapper/README.md --- zlibWrapper/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zlibWrapper/README.md b/zlibWrapper/README.md index 5572e3ec..81b3b224 100644 --- a/zlibWrapper/README.md +++ b/zlibWrapper/README.md @@ -1,7 +1,7 @@ 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. +The main objective of creating a zstd wrapper for [zlib](http://zlib.net/) is to allow a quick and smooth transition to zstd for projects already using zlib. #### Required files @@ -39,7 +39,7 @@ There is no switch for zstd decompression because zlib and zstd streams are auto #### Example -We have take the file ```test\example.c``` from the zlib library distribution and copied it to ```zlibWrapper\examples\example.c```. +We have take the file ```test\example.c``` from [the zlib library distribution](http://zlib.net/) and copied it to ```[zlibWrapper\examples\example.c](examples/example.c)```. After compilation and execution it shows the following results: ``` zlib version 1.2.8 = 0x1280, compile flags = 0x65 @@ -51,9 +51,9 @@ 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```. +Then we have compiled the ```[example.c](examples/example.c)``` file with ```-DZWRAP_USE_ZSTD=1``` and linked with additional ```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: +After running it shows the following results: ``` zlib version 1.2.8 = 0x1280, compile flags = 0x65 uncompress(): hello, hello! @@ -61,11 +61,11 @@ inflate(): hello, hello! large_inflate(): OK inflate with dictionary: hello, hello! ``` -The script used for compilation can be found at [zlibWrapper\Makefile](.\Makefile). +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. +After enabling zstd compression not all native zlib functions are supported. When calling unsupported methods they print error message and return an error value. Supported methods: - deflateInit From 37aba8b1d9de645a92de987f530dc770c09056ba Mon Sep 17 00:00:00 2001 From: inikep Date: Thu, 12 May 2016 17:32:28 +0200 Subject: [PATCH 4/5] updated zlibWrapper/README.md (2) --- zlibWrapper/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zlibWrapper/README.md b/zlibWrapper/README.md index 81b3b224..ccc8c3ff 100644 --- a/zlibWrapper/README.md +++ b/zlibWrapper/README.md @@ -39,7 +39,7 @@ There is no switch for zstd decompression because zlib and zstd streams are auto #### Example -We have take the file ```test\example.c``` from [the zlib library distribution](http://zlib.net/) and copied it to ```[zlibWrapper\examples\example.c](examples/example.c)```. +We have take the file ```test/example.c``` from [the zlib library distribution](http://zlib.net/) and copied it to [zlibWrapper/examples/example.c](examples/example.c). After compilation and execution it shows the following results: ``` zlib version 1.2.8 = 0x1280, compile flags = 0x65 @@ -51,7 +51,7 @@ large_inflate(): OK after inflateSync(): hello, hello! inflate with dictionary: hello, hello! ``` -Then we have compiled the ```[example.c](examples/example.c)``` file with ```-DZWRAP_USE_ZSTD=1``` and linked with additional ```zlib_wrapper.o -lzstd```. +Then we have compiled the [example.c](examples/example.c) file with ```-DZWRAP_USE_ZSTD=1``` and linked with additional ```zlib_wrapper.o -lzstd```. We have also turned of the following functions: test_gzio, test_flush, test_sync which use currently unsupported features. After running it shows the following results: ``` @@ -61,7 +61,7 @@ inflate(): hello, hello! large_inflate(): OK inflate with dictionary: hello, hello! ``` -The script used for compilation can be found at [zlibWrapper\Makefile](Makefile). +The script used for compilation can be found at [zlibWrapper/Makefile](Makefile). #### Compatibility issues From 0bdb6a81185c7df17af386441e6d729767a64a81 Mon Sep 17 00:00:00 2001 From: inikep Date: Fri, 13 May 2016 10:52:02 +0200 Subject: [PATCH 5/5] changed definition of UTIL_createFileList --- programs/bench.c | 2 +- programs/util.h | 52 ++++++++++++++++++++++++------------------- zlibWrapper/README.md | 7 +++--- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/programs/bench.c b/programs/bench.c index bc77fe05..bed7d16b 100644 --- a/programs/bench.c +++ b/programs/bench.c @@ -513,7 +513,7 @@ int BMK_benchFiles(const char** fileNamesTable, unsigned nbFiles, char* buf; const char** filenameTable; unsigned i; - nbFiles = UTIL_createFileList(fileNamesTable, nbFiles, &filenameTable, &buf); + filenameTable = UTIL_createFileList(fileNamesTable, nbFiles, &buf, &nbFiles); if (filenameTable) { for (i=0; i bufend) { free(buf); free((void*)fileTable); return NULL; } + + *allocatedBuffer = buf; + *allocatedNamesNb = nbFiles; + + return fileTable; } -UTIL_STATIC void UTIL_freeFileList(const char** filenameTable, char* buf) +UTIL_STATIC void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer) { - free(buf); - free((void*)filenameTable); + if (allocatedBuffer) free(allocatedBuffer); + if (filenameTable) free((void*)filenameTable); } diff --git a/zlibWrapper/README.md b/zlibWrapper/README.md index ccc8c3ff..272f7b99 100644 --- a/zlibWrapper/README.md +++ b/zlibWrapper/README.md @@ -29,7 +29,7 @@ The linking should be changed to: ```gcc project.o zlib_wrapper.o -lz -lzstd``` -#### Using the zstd wrapper with your project +#### Enabling zstd compression within 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: @@ -51,8 +51,9 @@ large_inflate(): OK after inflateSync(): hello, hello! inflate with dictionary: hello, hello! ``` -Then we have compiled the [example.c](examples/example.c) file with ```-DZWRAP_USE_ZSTD=1``` and linked with additional ```zlib_wrapper.o -lzstd```. -We have also turned of the following functions: test_gzio, test_flush, test_sync which use currently unsupported features. +Then we have changed ```#include "zlib.h"``` to ```#include "zstd_zlibwrapper.h"```, compiled the [example.c](examples/example.c) file +with ```-DZWRAP_USE_ZSTD=1``` and linked with additional ```zlib_wrapper.o -lzstd```. +We were forced to turn off the following functions: ```test_gzio```, ```test_flush```, ```test_sync``` which use currently unsupported features. After running it shows the following results: ``` zlib version 1.2.8 = 0x1280, compile flags = 0x65