Merge pull request #183 from inikep/dev

added zlibWrapper - zstd wrapper for zlib
This commit is contained in:
Yann Collet 2016-05-13 11:24:14 +02:00
commit ea7e4f0216
10 changed files with 2449 additions and 73 deletions

View File

@ -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);
filenameTable = UTIL_createFileList(fileNamesTable, nbFiles, &buf, &nbFiles);
if (filenameTable) {
for (i=0; i<nbFiles; i++) DISPLAYLEVEL(3, "%d %s\n", i, filenameTable[i]);
BMK_benchFileTable(filenameTable, nbFiles, dictFileName, cLevel, cLevelLast);

View File

@ -56,13 +56,19 @@ extern "C" {
/*-****************************************
* Dependencies
******************************************/
#include <stdlib.h> /* _POSIX_C_SOURCE, malloc */
#include <stdlib.h> /* features.h with _POSIX_C_SOURCE, malloc */
#include <stdio.h> /* fprintf */
#include <sys/types.h> /* stat */
#include <sys/stat.h> /* 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 <limits.h> /* PATH_MAX */
# include <errno.h>
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)) != NULL) {
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,62 +315,79 @@ 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_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
* and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
* After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
* In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
*/
UTIL_STATIC const char** UTIL_createFileList(const char **inputNames, unsigned inputNamesNb, char** allocatedBuffer, unsigned* allocatedNamesNb)
{
unsigned i, nbFiles = 0;
char *pbuf, *bufend, *buf;
size_t pos;
unsigned i, nbFiles;
char *bufend, *buf;
const char** fileTable;
buf = (char*)malloc(maxListSize);
if (!buf) { *filenameTable = NULL; return 0; }
bufend = buf + maxListSize;
buf = (char*)malloc(LIST_SIZE_INCREASE);
if (!buf) return NULL;
bufend = buf + LIST_SIZE_INCREASE;
for (i=0, pbuf = buf; i<nbNames; i++) {
for (i=0, pos=0, nbFiles=0; i<inputNamesNb; i++) {
if (UTIL_doesFileExists(inputNames[i])) {
// printf ("UTIL_doesFileExists=[%s]\n", inputNames[i]);
size_t len = strlen(inputNames[i]);
if (pbuf + len >= 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) return NULL;
}
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);
}
{ const char** fileTable = (const char**)malloc((nbFiles+1) * sizeof(const char*));
if (!fileTable) { free(buf); *filenameTable = NULL; return 0; }
if (nbFiles == 0)
fileTable[0] = buf;
for (i=0, pbuf = buf; i<nbFiles; i++)
{
fileTable[i] = pbuf;
pbuf += strlen(pbuf) + 1;
nbFiles += UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend);
if (buf == NULL) return NULL;
}
*filenameTable = fileTable;
*allocatedBuffer = buf;
}
return nbFiles;
if (nbFiles == 0) { free(buf); return NULL; }
fileTable = (const char**)malloc((nbFiles+1) * sizeof(const char*));
if (!fileTable) { free(buf); return NULL; }
for (i=0, pos=0; i<nbFiles; i++)
{
fileTable[i] = buf + pos;
pos += strlen(fileTable[i]) + 1;
}
if (buf + pos > 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);
}

View File

@ -28,12 +28,6 @@
*/
/*-************************************
* Compiler Options
**************************************/
#define _POSIX_SOURCE 1 /* triggers fileno() within <stdio.h> 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 <stdio.h> on POSIX */
# include <unistd.h> /* isatty */
# define SET_BINARY_MODE(file)
# define IS_CONSOLE(stdStream) isatty(fileno(stdStream))

26
zlibWrapper/.gitignore vendored Normal file
View File

@ -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

54
zlibWrapper/Makefile Normal file
View File

@ -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

105
zlibWrapper/README.md Normal file
View File

@ -0,0 +1,105 @@
zstd wrapper for 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
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```
#### 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:
- 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](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
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 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
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 native zlib functions are supported. When calling unsupported methods they 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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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 */