2 * Used by System.IO.Compression.DeflateStream
5 * Gonzalo Paniagua Javier (gonzalo@novell.com)
7 * (c) Copyright 2009 Novell, Inc.
10 #if defined (HAVE_ZLIB)
24 #define BUFFER_SIZE 4096
25 #define ARGUMENT_ERROR -10
28 typedef int (*read_write_func) (unsigned char *buffer, int length);
31 unsigned char *buffer;
33 unsigned char compress;
36 typedef struct _ZStream ZStream;
38 ZStream *CreateZStream (int compress, unsigned char gzip, read_write_func func);
39 int CloseZStream (ZStream *zstream);
40 int Flush (ZStream *stream);
41 int ReadZStream (ZStream *stream, unsigned char *buffer, int length);
42 int WriteZStream (ZStream *stream, unsigned char *buffer, int length);
46 CreateZStream (int compress, unsigned char gzip, read_write_func func)
55 #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
56 /* Older versions of zlib do not support raw deflate or gzip */
60 z = (z_stream *) malloc (sizeof (z_stream));
63 memset (z, 0, sizeof (z_stream));
65 retval = deflateInit2 (z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, gzip ? 31 : -15, 8, Z_DEFAULT_STRATEGY);
67 retval = inflateInit2 (z, gzip ? 31 : -15);
74 result = malloc (sizeof (ZStream));
75 memset (result, 0, sizeof (ZStream));
78 result->compress = compress;
79 result->buffer = (unsigned char *) malloc (BUFFER_SIZE);
80 if (result->buffer == NULL) {
90 memset (result->buffer, 0, BUFFER_SIZE);
95 CloseZStream (ZStream *zstream)
101 return ARGUMENT_ERROR;
104 if (zstream->compress) {
105 status = deflate (zstream->stream, Z_FINISH);
106 flush_status = Flush (zstream);
107 if (status == Z_OK || status == Z_STREAM_END)
108 status = flush_status;
109 deflateEnd (zstream->stream);
111 inflateEnd (zstream->stream);
113 free (zstream->buffer);
114 free (zstream->stream);
115 memset (zstream, 0, sizeof (ZStream));
121 write_to_managed (ZStream *stream)
127 if (zs->avail_out != BUFFER_SIZE) {
128 n = stream->func (stream->buffer, BUFFER_SIZE - zs->avail_out);
129 zs->next_out = stream->buffer;
130 zs->avail_out = BUFFER_SIZE;
138 Flush (ZStream *stream)
140 if (!stream->compress)
143 return write_to_managed (stream);
147 ReadZStream (ZStream *stream, unsigned char *buffer, int length)
153 if (stream == NULL || buffer == NULL || length < 0)
154 return ARGUMENT_ERROR;
160 zs->next_out = buffer;
161 zs->avail_out = length;
162 while (zs->avail_out > 0) {
163 if (zs->avail_in == 0) {
164 n = stream->func (stream->buffer, BUFFER_SIZE);
169 zs->next_in = stream->buffer;
173 status = inflate (stream->stream, Z_SYNC_FLUSH);
174 if (status != Z_OK && status != Z_STREAM_END)
177 return length - zs->avail_out;
181 WriteZStream (ZStream *stream, unsigned char *buffer, int length)
187 if (stream == NULL || buffer == NULL || length < 0)
188 return ARGUMENT_ERROR;
194 zs->next_in = buffer;
195 zs->avail_in = length;
196 while (zs->avail_in > 0) {
197 if (zs->avail_out == 0) {
198 zs->next_out = stream->buffer;
199 zs->avail_out = BUFFER_SIZE;
201 status = deflate (stream->stream, Z_SYNC_FLUSH);
202 if (status != Z_OK && status != Z_STREAM_END)
205 if (zs->avail_out == 0) {
206 n = write_to_managed (stream);