Skip to content

Instantly share code, notes, and snippets.

@hitxiang
Last active August 29, 2015 14:01
Show Gist options
  • Save hitxiang/6fc2fa47abaa86f63c51 to your computer and use it in GitHub Desktop.
Save hitxiang/6fc2fa47abaa86f63c51 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "zlib.h"
//#define CHUNK 16384
#define CHUNK 1024
#define INFLAT_RATE 16
#define DEFLAT_RATE 1.2
/*
* Please use compressBound + compress2 instead.
*/
/*
Compress from in-memory buffer to another in-memory buffer.
atl_zlib_def() returns Z_OK on success,
Z_MEM_ERROR if memory could not be allocated for processing,
Z_DATA_ERROR if the deflate data is invalid or incomplete,
Z_VERSION_ERROR if the version of zlib.h and the version of the library linked do not match
*/
int atl_zlib_def(char **dest, size_t *dest_len, const char *source, size_t src_len, int level)
{
if (!source || src_len == 0) {
*dest = "";
*dest_len = 0;
return Z_OK;
}
int ret, flush;
size_t in_avail_len, in_left_len = src_len, out_done_len=0;
size_t comp_inc = src_len * DEFLAT_RATE;
const char *in_ptr = source;
char *out_ptr = NULL, *out_tmp_ptr;
/* allocate deflate state */
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&strm, level);
if (ret != Z_OK)
return ret;
do {
if ( in_left_len > CHUNK ) {
in_avail_len = CHUNK;
in_left_len -= CHUNK;
} else {
in_avail_len = in_left_len;
in_left_len = 0;
}
flush = (in_left_len == 0) ? Z_FINISH : Z_NO_FLUSH;
strm.avail_in = in_avail_len;
strm.next_in = (Bytef *)in_ptr;
/* run deflate() on input until output buffer not full, finish
compression if all of source has been read in */
do {
if (out_ptr == NULL) {
out_ptr = (char*) calloc( sizeof(char), comp_inc );
} else {
out_tmp_ptr = (char*) calloc( sizeof(char), out_done_len + comp_inc );
memcpy(out_tmp_ptr, out_ptr, out_done_len);
free(out_ptr);
out_ptr = out_tmp_ptr;
}
strm.avail_out = comp_inc;
strm.next_out = (Bytef *)(out_ptr + out_done_len);
ret = deflate(&strm, flush); /* no bad return value */
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
out_done_len += (comp_inc - strm.avail_out);
} while (strm.avail_out == 0);
assert(strm.avail_in == 0); /* all input will be used */
in_ptr += in_avail_len;
} while (flush != Z_FINISH);
assert(ret == Z_STREAM_END); /* stream will be complete */
*dest_len = out_done_len;
*dest = out_ptr;
/* clean up and return */
(void)deflateEnd(&strm);
return Z_OK;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "zlib.h"
//#define CHUNK 16384
#define CHUNK 1024
#define INFLAT_RATE 16
#define DEFLAT_RATE 1.2
/*
Decompress from in-memory buffer to another in-memory buffer.
atl_zlib_inf() returns Z_OK on success,
Z_MEM_ERROR if memory could not be allocated for processing,
Z_DATA_ERROR if the deflate data is invalid or incomplete,
Z_VERSION_ERROR if the version of zlib.h and the version of the library linked do not match
*/
int atl_zlib_inf(char **dest, size_t *dest_len, const char *source, size_t src_len)
{
if (!source || src_len == 0) {
*dest = "";
*dest_len = 0;
return Z_OK;
}
int ret;
size_t in_avail_len, in_left_len = src_len, out_done_len=0;
size_t uncomp_inc = src_len * INFLAT_RATE;
const char *in_ptr = source;
char *out_ptr = NULL, *out_tmp_ptr;
/* allocate inflate state */
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
/* decompress until deflate stream ends or end of file */
do {
if ( in_left_len > CHUNK ) {
in_avail_len = CHUNK;
in_left_len -= CHUNK;
} else {
in_avail_len = in_left_len;
in_left_len = 0;
}
if (in_avail_len == 0)
break;
strm.avail_in = in_avail_len;
strm.next_in = (Bytef *)in_ptr;
/* run inflate() on input until output buffer not full */
do {
if (out_ptr == NULL) {
out_ptr = (char*) calloc( sizeof(char), uncomp_inc );
} else {
out_tmp_ptr = (char*) calloc( sizeof(char), out_done_len + uncomp_inc );
memcpy(out_tmp_ptr, out_ptr, out_done_len);
free(out_ptr);
out_ptr = out_tmp_ptr;
}
strm.avail_out = uncomp_inc;
strm.next_out = (Bytef *)(out_ptr + out_done_len);
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
out_done_len += (uncomp_inc - strm.avail_out);
} while (strm.avail_out == 0);
in_ptr += in_avail_len;
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
*dest_len = out_done_len;
*dest = out_ptr;
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
static void zerr(int ret)
{
fputs("atl_zlib: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}
/* compress or decompress from stdin to stdout */
int main(int argc, char **argv)
{
int ret;
size_t buffer_len = 1024*512;
char buffer[buffer_len];
char *rslt_str;
size_t rslt_len;
/* do compression if no arguments */
if (argc == 1) {
size_t real_len = fread(buffer, 1, buffer_len, stdin);
if (real_len == buffer_len)
fputs("Please increase buffer", stderr);
//ret = atl_zlib_def(&rslt_str, &rslt_len, buffer, real_len, Z_DEFAULT_COMPRESSION);
rslt_len = compressBound(real_len);
rslt_str = (char*)malloc(rslt_len);
ret = compress2((Bytef*)rslt_str, &rslt_len , (Bytef*)buffer, real_len, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
zerr(ret);
fwrite(rslt_str, 1, rslt_len, stdout);
free(rslt_str);
return ret;
}
/* do decompression if -d specified */
else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
size_t real_len = fread(buffer, 1, buffer_len, stdin);
if (real_len == buffer_len)
fputs("Please increase buffer\n", stderr);
ret = atl_zlib_inf(&rslt_str, &rslt_len , buffer, real_len);
if (ret != Z_OK)
zerr(ret);
fwrite(rslt_str, 1, rslt_len, stdout);
free(rslt_str);
return ret;
}
/* otherwise, report usage */
else {
fputs("atl_zlib usage: atl_zlib [-d] < source > dest\n", stderr);
return 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment