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, void *gchandle);
38 typedef struct _ZStream ZStream;
40 ZStream *CreateZStream (gint compress, guchar gzip, read_write_func func, void *gchandle);
41 gint CloseZStream (ZStream *zstream);
42 gint Flush (ZStream *stream);
43 gint ReadZStream (ZStream *stream, guchar *buffer, gint length);
44 gint WriteZStream (ZStream *stream, guchar *buffer, gint length);
47 z_alloc (void *opaque, gsize nitems, gsize item_size)
49 return g_malloc0 (nitems * item_size);
53 z_free (void *opaque, void *ptr)
59 CreateZStream (gint compress, guchar gzip, read_write_func func, void *gchandle)
68 #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
69 /* Older versions of zlib do not support raw deflate or gzip */
73 z = g_new0 (z_stream, 1);
75 retval = deflateInit2 (z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, gzip ? 31 : -15, 8, Z_DEFAULT_STRATEGY);
77 retval = inflateInit2 (z, gzip ? 31 : -15);
86 result = g_new0 (ZStream, 1);
89 result->gchandle = gchandle;
90 result->compress = compress;
91 result->buffer = g_new (guchar, BUFFER_SIZE);
96 CloseZStream (ZStream *zstream)
102 return ARGUMENT_ERROR;
105 if (zstream->compress) {
106 if (zstream->stream->total_out) {
107 status = deflate (zstream->stream, Z_FINISH);
108 flush_status = Flush (zstream);
109 if (status == Z_OK || status == Z_STREAM_END)
110 status = flush_status;
112 deflateEnd (zstream->stream);
114 inflateEnd (zstream->stream);
116 g_free (zstream->buffer);
117 g_free (zstream->stream);
118 memset (zstream, 0, sizeof (ZStream));
124 write_to_managed (ZStream *stream)
130 if (zs->avail_out != BUFFER_SIZE) {
131 n = stream->func (stream->buffer, BUFFER_SIZE - zs->avail_out, stream->gchandle);
132 zs->next_out = stream->buffer;
133 zs->avail_out = BUFFER_SIZE;
141 Flush (ZStream *stream)
143 if (!stream->compress)
146 return write_to_managed (stream);
150 ReadZStream (ZStream *stream, guchar *buffer, gint length)
156 if (stream == NULL || buffer == NULL || length < 0)
157 return ARGUMENT_ERROR;
163 zs->next_out = buffer;
164 zs->avail_out = length;
165 while (zs->avail_out > 0) {
166 if (zs->avail_in == 0) {
167 n = stream->func (stream->buffer, BUFFER_SIZE, stream->gchandle);
172 zs->next_in = stream->buffer;
176 status = inflate (stream->stream, Z_SYNC_FLUSH);
177 if (status == Z_STREAM_END) {
180 } else if (status != Z_OK) {
184 return length - zs->avail_out;
188 WriteZStream (ZStream *stream, guchar *buffer, gint length)
194 if (stream == NULL || buffer == NULL || length < 0)
195 return ARGUMENT_ERROR;
201 zs->next_in = buffer;
202 zs->avail_in = length;
203 while (zs->avail_in > 0) {
204 if (zs->avail_out == 0) {
205 zs->next_out = stream->buffer;
206 zs->avail_out = BUFFER_SIZE;
208 status = deflate (stream->stream, Z_SYNC_FLUSH);
209 if (status != Z_OK && status != Z_STREAM_END)
212 if (zs->avail_out == 0) {
213 n = write_to_managed (stream);