Merge pull request #2386 from BrzVlad/fix-jit
[mono.git] / support / zlib-helper.c
index 23c662bf74d6f2e878d1802ba65a5810d72ce840..dbfd1c7e24a27e7dd67283e6c1df7401b17d6100 100644 (file)
@@ -42,9 +42,10 @@ gint CloseZStream (ZStream *zstream);
 gint Flush (ZStream *stream);
 gint ReadZStream (ZStream *stream, guchar *buffer, gint length);
 gint WriteZStream (ZStream *stream, guchar *buffer, gint length);
+static gint flush_internal (ZStream *stream, gboolean is_final);
 
 static void *
-z_alloc (void *opaque, gsize nitems, gsize item_size)
+z_alloc (void *opaque, unsigned int nitems, unsigned int item_size)
 {
        return g_malloc0 (nitems * item_size);
 }
@@ -89,6 +90,8 @@ CreateZStream (gint compress, guchar gzip, read_write_func func, void *gchandle)
        result->gchandle = gchandle;
        result->compress = compress;
        result->buffer = g_new (guchar, BUFFER_SIZE);
+       result->stream->next_out = result->buffer;
+       result->stream->avail_out = BUFFER_SIZE;
        return result;
 }
 
@@ -103,12 +106,14 @@ CloseZStream (ZStream *zstream)
 
        status = 0;
        if (zstream->compress) {
-               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;
+               if (zstream->stream->total_in > 0) {
+                       do {
+                               status = deflate (zstream->stream, Z_FINISH);
+                               flush_status = flush_internal (zstream, TRUE);
+                       } while (status == Z_OK); /* We want Z_STREAM_END or error here here */
+                       if (status == Z_STREAM_END)
+                               status = flush_status;
+               }
                deflateEnd (zstream->stream);
        } else {
                inflateEnd (zstream->stream);
@@ -130,22 +135,35 @@ write_to_managed (ZStream *stream)
        if (zs->avail_out != BUFFER_SIZE) {
                n = stream->func (stream->buffer, BUFFER_SIZE - zs->avail_out, stream->gchandle);
                zs->next_out = stream->buffer;
-               zs->avail_out =  BUFFER_SIZE;
+               zs->avail_out = BUFFER_SIZE;
                if (n < 0)
                        return IO_ERROR;
        }
        return 0;
 }
 
-gint
-Flush (ZStream *stream)
+static gint
+flush_internal (ZStream *stream, gboolean is_final)
 {
+       gint status;
+
        if (!stream->compress)
                return 0;
 
+       if (!is_final && stream->stream->avail_in != 0) {
+               status = deflate (stream->stream, Z_PARTIAL_FLUSH);
+               if (status != Z_OK && status != Z_STREAM_END)
+                       return status;
+       }
        return write_to_managed (stream);
 }
 
+gint
+Flush (ZStream *stream)
+{
+       return flush_internal (stream, FALSE);
+}
+
 gint
 ReadZStream (ZStream *stream, guchar *buffer, gint length)
 {
@@ -167,12 +185,14 @@ ReadZStream (ZStream *stream, guchar *buffer, gint length)
                        n = stream->func (stream->buffer, BUFFER_SIZE, stream->gchandle);
                        if (n <= 0) {
                                stream->eof = TRUE;
-                               break;
                        }
                        zs->next_in = stream->buffer;
-                       zs->avail_in = n;
+                       zs->avail_in = n < 0 ? 0 : n;
                }
 
+               if (zs->avail_in == 0 && zs->total_in == 0)
+                       return Z_STREAM_END;
+
                status = inflate (stream->stream, Z_SYNC_FLUSH);
                if (status == Z_STREAM_END) {
                        stream->eof = TRUE;