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)
25 #define BUFFER_SIZE 4096
26 #define ARGUMENT_ERROR -10
29 typedef gint (*read_write_func) (guchar *buffer, gint length);
37 typedef struct _ZStream ZStream;
39 ZStream *CreateZStream (gint compress, guchar gzip, read_write_func func);
40 gint CloseZStream (ZStream *zstream);
41 gint Flush (ZStream *stream);
42 gint ReadZStream (ZStream *stream, guchar *buffer, gint length);
43 gint WriteZStream (ZStream *stream, guchar *buffer, gint length);
46 z_alloc (void *opaque, gsize nitems, gsize item_size)
48 return g_malloc0 (nitems * item_size);
52 z_free (void *opaque, void *ptr)
58 CreateZStream (gint compress, guchar gzip, read_write_func func)
67 #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
68 /* Older versions of zlib do not support raw deflate or gzip */
72 z = g_new0 (z_stream, 1);
74 retval = deflateInit2 (z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, gzip ? 31 : -15, 8, Z_DEFAULT_STRATEGY);
76 retval = inflateInit2 (z, gzip ? 31 : -15);
85 result = g_new0 (ZStream, 1);
88 result->compress = compress;
89 result->buffer = g_new (guchar, BUFFER_SIZE);
94 CloseZStream (ZStream *zstream)
100 return ARGUMENT_ERROR;
103 if (zstream->compress) {
104 if (zstream->stream->total_out) {
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;
110 deflateEnd (zstream->stream);
112 inflateEnd (zstream->stream);
114 g_free (zstream->buffer);
115 g_free (zstream->stream);
116 memset (zstream, 0, sizeof (ZStream));
122 write_to_managed (ZStream *stream)
128 if (zs->avail_out != BUFFER_SIZE) {
129 n = stream->func (stream->buffer, BUFFER_SIZE - zs->avail_out);
130 zs->next_out = stream->buffer;
131 zs->avail_out = BUFFER_SIZE;
139 Flush (ZStream *stream)
141 if (!stream->compress)
144 return write_to_managed (stream);
148 ReadZStream (ZStream *stream, guchar *buffer, gint length)
154 if (stream == NULL || buffer == NULL || length < 0)
155 return ARGUMENT_ERROR;
161 zs->next_out = buffer;
162 zs->avail_out = length;
163 while (zs->avail_out > 0) {
164 if (zs->avail_in == 0) {
165 n = stream->func (stream->buffer, BUFFER_SIZE);
170 zs->next_in = stream->buffer;
174 status = inflate (stream->stream, Z_SYNC_FLUSH);
175 if (status != Z_OK && status != Z_STREAM_END)
178 return length - zs->avail_out;
182 WriteZStream (ZStream *stream, guchar *buffer, gint length)
188 if (stream == NULL || buffer == NULL || length < 0)
189 return ARGUMENT_ERROR;
195 zs->next_in = buffer;
196 zs->avail_in = length;
197 while (zs->avail_in > 0) {
198 if (zs->avail_out == 0) {
199 zs->next_out = stream->buffer;
200 zs->avail_out = BUFFER_SIZE;
202 status = deflate (stream->stream, Z_SYNC_FLUSH);
203 if (status != Z_OK && status != Z_STREAM_END)
206 if (zs->avail_out == 0) {
207 n = write_to_managed (stream);