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
);