Last active
May 25, 2020 13:45
-
-
Save nmoinvaz/fb9f806955b9dec77c09d3ec986c9442 to your computer and use it in GitHub Desktop.
Zlib-ng deflate parameter testing tool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* deflateparams.c -- test deflate under specific conditions | |
* Copyright (C) 2020 Nathan Moinvaziri | |
* For conditions of distribution and use, see copyright notice in zlib.h | |
*/ | |
/* | |
add_executable(deflateparams test/deflateparams.c) | |
configure_test_executable(deflateparams) | |
target_link_libraries(deflateparams zlib) | |
*/ | |
#include <stdio.h> | |
#include <stddef.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <stdlib.h> | |
#include <inttypes.h> | |
#include "zbuild.h" | |
#ifdef ZLIB_COMPAT | |
# include "zlib.h" | |
#else | |
# include "zlib-ng.h" | |
#endif | |
#if defined(WIN32) || defined(__CYGWIN__) | |
# include <fcntl.h> | |
# include <io.h> | |
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) | |
#else | |
# define SET_BINARY_MODE(file) | |
#endif | |
#if MAX_MEM_LEVEL >= 8 | |
# define DEF_MEM_LEVEL 8 | |
#else | |
# define DEF_MEM_LEVEL MAX_MEM_LEVEL | |
#endif | |
#define CHECK_ERR(err, msg) { \ | |
if (err != Z_OK) { \ | |
fprintf(stderr, "%s error: %d\n", msg, err); \ | |
exit(1); \ | |
} \ | |
} | |
static alloc_func zalloc = NULL; | |
static free_func zfree = NULL; | |
/* =========================================================================== | |
* deflate() using small buffers | |
*/ | |
void deflate_params_small(unsigned char *buf, uint32_t len, int level, int window_bits, int mem_level, int strategy) | |
{ | |
PREFIX3(stream) c_stream; /* compression stream */ | |
unsigned char compr[4096]; | |
int err; | |
c_stream.zalloc = zalloc; | |
c_stream.zfree = zfree; | |
c_stream.opaque = (void *)0; | |
c_stream.total_in = 0; | |
c_stream.total_out = 0; | |
err = PREFIX(deflateInit2)(&c_stream, level, Z_DEFLATED, window_bits, mem_level, strategy); | |
CHECK_ERR(err, "deflateInit2"); | |
c_stream.next_in = (const unsigned char *)buf; | |
c_stream.next_out = (unsigned char *)compr; | |
while (c_stream.total_in < len) { | |
c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ | |
err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); | |
CHECK_ERR(err, "deflate"); | |
if (c_stream.next_out == compr + sizeof(compr)) { | |
fwrite(compr, 1, (size_t)sizeof(compr), stdout); | |
c_stream.next_out = (unsigned char *)compr; | |
} | |
} | |
/* Finish the stream, still forcing small buffers: */ | |
c_stream.avail_in = 0; | |
do { | |
if (c_stream.next_out == compr + sizeof(compr)) { | |
fwrite(compr, 1, (size_t)sizeof(compr), stdout); | |
c_stream.next_out = (unsigned char *)compr; | |
} | |
c_stream.avail_out = 1; /* force small buffers */ | |
err = PREFIX(deflate)(&c_stream, Z_FINISH); | |
if (err == Z_STREAM_END) break; | |
CHECK_ERR(err, "deflate"); | |
} while (err == Z_OK); | |
if (c_stream.next_out != compr) { | |
fwrite(compr, 1, c_stream.next_out - compr, stdout); | |
} | |
err = PREFIX(deflateEnd)(&c_stream); | |
CHECK_ERR(err, "deflateEnd"); | |
} | |
/* =========================================================================== | |
* deflate() with large buffers | |
*/ | |
void deflate_params_large(unsigned char *buf, uint32_t len, int level, int window_bits, int mem_level, int strategy) | |
{ | |
PREFIX3(stream) c_stream; /* compression stream */ | |
unsigned char compr[4096]; | |
int err; | |
c_stream.zalloc = zalloc; | |
c_stream.zfree = zfree; | |
c_stream.opaque = (void *)0; | |
c_stream.total_in = 0; | |
c_stream.total_out = 0; | |
err = PREFIX(deflateInit2)(&c_stream, level, Z_DEFLATED, window_bits, mem_level, strategy); | |
CHECK_ERR(err, "deflateInit2"); | |
c_stream.next_in = (const unsigned char *)buf; | |
c_stream.next_out = (unsigned char *)compr; | |
while (c_stream.total_in < len) { | |
c_stream.avail_in = c_stream.avail_out = sizeof(compr); /* Force large buffers */ | |
if (c_stream.avail_in > (len - c_stream.total_in)) | |
c_stream.avail_in = (len - c_stream.total_in); | |
err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); | |
CHECK_ERR(err, "deflate"); | |
fwrite(compr, 1, c_stream.next_out - compr, stdout); | |
} | |
/* Finish the stream using large buffers */ | |
c_stream.avail_in = 0; | |
do { | |
c_stream.avail_out = sizeof(compr); | |
err = PREFIX(deflate)(&c_stream, Z_FINISH); | |
fwrite(compr, 1, c_stream.next_out - compr, stdout); | |
if (err == Z_STREAM_END) break; | |
CHECK_ERR(err, "deflate"); | |
} while (err == Z_OK); | |
err = PREFIX(deflateEnd)(&c_stream); | |
CHECK_ERR(err, "deflateEnd"); | |
} | |
/* =========================================================================== | |
* deflate() with params | |
*/ | |
void deflate_params(unsigned char *buf, uint32_t len, int level, int window_bits, int mem_level, int strategy) | |
{ | |
PREFIX3(stream) c_stream; /* compression stream */ | |
size_t compr_bound; | |
unsigned char *compr; | |
int err; | |
c_stream.zalloc = zalloc; | |
c_stream.zfree = zfree; | |
c_stream.opaque = (void *)0; | |
c_stream.total_in = 0; | |
c_stream.total_out = 0; | |
compr_bound = PREFIX(compressBound)(len); | |
compr = malloc(compr_bound); | |
assert(compr != NULL); | |
err = PREFIX(deflateInit2)(&c_stream, level, Z_DEFLATED, window_bits, mem_level, strategy); | |
CHECK_ERR(err, "deflateInit2"); | |
c_stream.next_in = (const unsigned char *)buf; | |
c_stream.avail_in = len; | |
c_stream.next_out = compr; | |
c_stream.avail_out = (uint32_t)compr_bound; | |
err = PREFIX(deflate)(&c_stream, Z_FINISH); | |
if (err != Z_STREAM_END) | |
CHECK_ERR(err, "deflate"); | |
err = PREFIX(deflateEnd)(&c_stream); | |
CHECK_ERR(err, "deflateEnd"); | |
fwrite(compr, 1, c_stream.total_out, stdout); | |
free(compr); | |
} | |
/* =========================================================================== | |
* Usage: deflateparams [-f] [-h] [-R] [-F] [-m 1 to 8] [-s] [-l] [-w #] [-0 to -9] [input file] | |
* -f : compress with Z_FILTERED | |
* -h : compress with Z_HUFFMAN_ONLY | |
* -R : compress with Z_RLE | |
* -F : compress with Z_FIXED | |
* -m : memory level 1-8 | |
* -s : small buffer | |
* -l : large buffer | |
* -w : window bits | |
* -0 to -9 : compression level | |
*/ | |
int main(int argc, char **argv) { | |
int32_t i; | |
int32_t mem_level = DEF_MEM_LEVEL; | |
int32_t window_bits = MAX_WBITS; | |
int32_t strategy = Z_DEFAULT_STRATEGY; | |
int32_t level = 6; | |
uint8_t small_buf = 0; | |
uint8_t large_buf = 0; | |
size_t len, read; | |
unsigned char *buf; | |
FILE *f; | |
for (i = 1; i < argc; i++) { | |
if ((strcmp(argv[i], "-m") == 0) && (i + 1 < argc)) | |
mem_level = atoi(argv[++i]); | |
else if ((strcmp(argv[i], "-w") == 0) && (i + 1 < argc)) | |
window_bits = atoi(argv[++i]); | |
else if (strcmp(argv[i], "-s") == 0) | |
small_buf = 1; | |
else if (strcmp(argv[i], "-l") == 0) | |
large_buf = 1; | |
else if (strcmp(argv[i], "-f") == 0) | |
strategy = Z_FILTERED; | |
else if (strcmp(argv[i], "-h") == 0) | |
strategy = Z_HUFFMAN_ONLY; | |
else if (strcmp(argv[i], "-R") == 0) | |
strategy = Z_RLE; | |
else if (argv[i][0] == '-' && argv[i][1] >= '0' && argv[i][1] <= '9' && argv[i][2] == 0) | |
level = argv[i][1] - '0'; | |
else | |
break; | |
} | |
printf("deflateParams: level %d memLevel %d windowBits %d strategy %d\n", level, mem_level, | |
window_bits, strategy); | |
if (i == argc) { | |
fprintf(stderr, "No input file specified\n"); | |
exit(1); | |
} | |
SET_BINARY_MODE(stdout); | |
f = fopen(argv[i], "rb+"); | |
if (f == NULL) { | |
/* Failed to open this file: it may be a directory. */ | |
fprintf(stderr, "Failed to open file: %s\n", argv[i]); | |
exit(1); | |
} | |
fseek(f, 0, SEEK_END); | |
len = ftell(f); | |
fseek(f, 0, SEEK_SET); | |
buf = (unsigned char *)malloc(len); | |
read = fread(buf, 1, len, f); | |
assert(read == len); | |
if (small_buf) { | |
deflate_params_small(buf, len, level, window_bits, mem_level, strategy); | |
} else if (large_buf) { | |
deflate_params_large(buf, len, level, window_bits, mem_level, strategy); | |
} else { | |
deflate_params(buf, len, level, window_bits, mem_level, strategy); | |
} | |
free(buf); | |
fclose(f); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment