Make gshared variables GC tracked.
[mono.git] / support / zlib-helper.c
index 9a692792b1066d9ebfad4226b8c1b1a93f7e9c90..66b58663a5eb6beff5f7b34638bc2a01fbd65d3c 100644 (file)
 #define ARGUMENT_ERROR -10
 #define IO_ERROR -11
 
-typedef gint (*read_write_func) (guchar *buffer, gint length);
+typedef gint (*read_write_func) (guchar *buffer, gint length, void *gchandle);
 struct _ZStream {
        z_stream *stream;
        guchar *buffer;
        read_write_func func;
+       void *gchandle;
        guchar compress;
        guchar eof;
 };
 typedef struct _ZStream ZStream;
 
-ZStream *CreateZStream (gint compress, guchar gzip, read_write_func func);
+ZStream *CreateZStream (gint compress, guchar gzip, read_write_func func, void *gchandle);
 gint CloseZStream (ZStream *zstream);
 gint Flush (ZStream *stream);
 gint ReadZStream (ZStream *stream, guchar *buffer, gint length);
@@ -55,7 +56,7 @@ z_free (void *opaque, void *ptr)
 }
 
 ZStream *
-CreateZStream (gint compress, guchar gzip, read_write_func func)
+CreateZStream (gint compress, guchar gzip, read_write_func func, void *gchandle)
 {
        z_stream *z;
        gint retval;
@@ -85,6 +86,7 @@ CreateZStream (gint compress, guchar gzip, read_write_func func)
        result = g_new0 (ZStream, 1);
        result->stream = z;
        result->func = func;
+       result->gchandle = gchandle;
        result->compress = compress;
        result->buffer = g_new (guchar, BUFFER_SIZE);
        return result;
@@ -101,10 +103,12 @@ CloseZStream (ZStream *zstream)
 
        status = 0;
        if (zstream->compress) {
-               if (zstream->stream->total_out) {
-                       status = deflate (zstream->stream, Z_FINISH);
-                       flush_status = Flush (zstream);
-                       if (status == Z_OK || status == Z_STREAM_END)
+               if (zstream->stream->total_in > 0) {
+                       do {
+                               status = deflate (zstream->stream, Z_FINISH);
+                               flush_status = Flush (zstream);
+                       } while (status == Z_OK); /* We want Z_STREAM_END or error here here */
+                       if (status == Z_STREAM_END)
                                status = flush_status;
                }
                deflateEnd (zstream->stream);
@@ -126,7 +130,7 @@ write_to_managed (ZStream *stream)
 
        zs = stream->stream;
        if (zs->avail_out != BUFFER_SIZE) {
-               n = stream->func (stream->buffer, BUFFER_SIZE - zs->avail_out);
+               n = stream->func (stream->buffer, BUFFER_SIZE - zs->avail_out, stream->gchandle);
                zs->next_out = stream->buffer;
                zs->avail_out =  BUFFER_SIZE;
                if (n < 0)
@@ -162,7 +166,7 @@ ReadZStream (ZStream *stream, guchar *buffer, gint length)
        zs->avail_out = length;
        while (zs->avail_out > 0) {
                if (zs->avail_in == 0) {
-                       n = stream->func (stream->buffer, BUFFER_SIZE);
+                       n = stream->func (stream->buffer, BUFFER_SIZE, stream->gchandle);
                        if (n <= 0) {
                                stream->eof = TRUE;
                                break;
@@ -172,8 +176,12 @@ ReadZStream (ZStream *stream, guchar *buffer, gint length)
                }
 
                status = inflate (stream->stream, Z_SYNC_FLUSH);
-               if (status != Z_OK && status != Z_STREAM_END)
+               if (status == Z_STREAM_END) {
+                       stream->eof = TRUE;
+                       break;
+               } else if (status != Z_OK) {
                        return status;
+               }
        }
        return length - zs->avail_out;
 }
@@ -199,7 +207,7 @@ WriteZStream (ZStream *stream, guchar *buffer, gint length)
                        zs->next_out = stream->buffer;
                        zs->avail_out = BUFFER_SIZE;
                }
-               status = deflate (stream->stream, Z_SYNC_FLUSH);
+               status = deflate (stream->stream, Z_NO_FLUSH);
                if (status != Z_OK && status != Z_STREAM_END)
                        return status;