/*
 * Helper routines to use Zlib
 *
 * Author:
 *   Christopher Lahey (clahey@ximian.co)
 *
 * (C) 2004 Novell, Inc.
 */
#include <zlib.h>
#include <stdlib.h>

/** new section for error output - Xobni Corp. (adam.smith@xobni.com) - 11/6/2006 **/
#include <stdio.h>

/* report a zlib or I/O error */
void zerr(int ret)
{
    fputs("zpipe: ", 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);
    }
}
/** end of new section **/

z_stream *
create_z_stream(int compress, unsigned char gzip)
{
	z_stream *z;
	int retval;

#if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
	/* Older versions of zlib do not support raw deflate or gzip */
	return NULL;
#endif

	z = malloc (sizeof (z_stream));
	z->next_in = Z_NULL;
	z->avail_in = 0;
	z->next_out = Z_NULL;
	z->avail_out = 0;
	z->zalloc = Z_NULL;
	z->zfree = Z_NULL;
	z->opaque = NULL;
	if (compress) {
		retval = deflateInit2 (z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, gzip ? 31 : -15, 8, Z_DEFAULT_STRATEGY);
	} else {
		retval = inflateInit2 (z, gzip ? 31 : -15);
	}

	if (retval == Z_OK)
		return z;

   // new section for error output - Xobni Corp. (adam.smith@xobni.com) - 11/6/2006
   else
      zerr(retval);
   // end of new section for error output
   
	free (z);
	return NULL;
}

void
free_z_stream(z_stream *z, int compress)
{
	if (compress) {
		deflateEnd (z);
	} else {
		inflateEnd (z);
	}
	free (z);
}

void
z_stream_set_next_in(z_stream *z, unsigned char *next_in)
{
	z->next_in = next_in;
}

void
z_stream_set_avail_in(z_stream *z, int avail_in)
{
	z->avail_in = avail_in;
}

int
z_stream_get_avail_in(z_stream *z)
{
	return z->avail_in;
}

void
z_stream_set_next_out(z_stream *z, unsigned char *next_out)
{
	z->next_out = next_out;
}

void
z_stream_set_avail_out(z_stream *z, int avail_out)
{
	z->avail_out = avail_out;
}

int
z_stream_deflate (z_stream *z, int flush, unsigned char *next_out, int *avail_out)
{
	int ret_val;

	z->next_out = next_out;
	z->avail_out = *avail_out;

	ret_val = deflate (z, flush);

	*avail_out = z->avail_out;

	return ret_val;
}

int
z_stream_inflate (z_stream *z, int *avail_out)
{
	int ret_val;

	z->avail_out = *avail_out;

	ret_val = inflate (z, Z_NO_FLUSH);

	*avail_out = z->avail_out;

	return ret_val;
}

