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
);
45 static gint
flush_internal (ZStream
*stream
, gboolean is_final
);
48 z_alloc (void *opaque
, unsigned int nitems
, unsigned int item_size
)
50 return g_malloc0 (nitems
* item_size
);
54 z_free (void *opaque
, void *ptr
)
60 CreateZStream (gint compress
, guchar gzip
, read_write_func func
, void *gchandle
)
69 #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
70 /* Older versions of zlib do not support raw deflate or gzip */
74 z
= g_new0 (z_stream
, 1);
76 retval
= deflateInit2 (z
, Z_DEFAULT_COMPRESSION
, Z_DEFLATED
, gzip
? 31 : -15, 8, Z_DEFAULT_STRATEGY
);
78 retval
= inflateInit2 (z
, gzip
? 31 : -15);
87 result
= g_new0 (ZStream
, 1);
90 result
->gchandle
= gchandle
;
91 result
->compress
= compress
;
92 result
->buffer
= g_new (guchar
, BUFFER_SIZE
);
93 result
->stream
->next_out
= result
->buffer
;
94 result
->stream
->avail_out
= BUFFER_SIZE
;
99 CloseZStream (ZStream
*zstream
)
105 return ARGUMENT_ERROR
;
108 if (zstream
->compress
) {
109 if (zstream
->stream
->total_in
> 0) {
111 status
= deflate (zstream
->stream
, Z_FINISH
);
112 flush_status
= flush_internal (zstream
, TRUE
);
113 } while (status
== Z_OK
); /* We want Z_STREAM_END or error here here */
114 if (status
== Z_STREAM_END
)
115 status
= flush_status
;
117 deflateEnd (zstream
->stream
);
119 inflateEnd (zstream
->stream
);
121 g_free (zstream
->buffer
);
122 g_free (zstream
->stream
);
123 memset (zstream
, 0, sizeof (ZStream
));
129 write_to_managed (ZStream
*stream
)
135 if (zs
->avail_out
!= BUFFER_SIZE
) {
136 n
= stream
->func (stream
->buffer
, BUFFER_SIZE
- zs
->avail_out
, stream
->gchandle
);
137 zs
->next_out
= stream
->buffer
;
138 zs
->avail_out
= BUFFER_SIZE
;
146 flush_internal (ZStream
*stream
, gboolean is_final
)
150 if (!stream
->compress
)
153 if (!is_final
&& stream
->stream
->avail_in
!= 0) {
154 status
= deflate (stream
->stream
, Z_PARTIAL_FLUSH
);
155 if (status
!= Z_OK
&& status
!= Z_STREAM_END
)
158 return write_to_managed (stream
);
162 Flush (ZStream
*stream
)
164 return flush_internal (stream
, FALSE
);
168 ReadZStream (ZStream
*stream
, guchar
*buffer
, gint length
)
174 if (stream
== NULL
|| buffer
== NULL
|| length
< 0)
175 return ARGUMENT_ERROR
;
181 zs
->next_out
= buffer
;
182 zs
->avail_out
= length
;
183 while (zs
->avail_out
> 0) {
184 if (zs
->avail_in
== 0) {
185 n
= stream
->func (stream
->buffer
, BUFFER_SIZE
, stream
->gchandle
);
189 zs
->next_in
= stream
->buffer
;
193 if (zs
->avail_in
== 0 && zs
->total_in
== 0)
196 status
= inflate (stream
->stream
, Z_SYNC_FLUSH
);
197 if (status
== Z_STREAM_END
) {
200 } else if (status
!= Z_OK
) {
204 return length
- zs
->avail_out
;
208 WriteZStream (ZStream
*stream
, guchar
*buffer
, gint length
)
214 if (stream
== NULL
|| buffer
== NULL
|| length
< 0)
215 return ARGUMENT_ERROR
;
221 zs
->next_in
= buffer
;
222 zs
->avail_in
= length
;
223 while (zs
->avail_in
> 0) {
224 if (zs
->avail_out
== 0) {
225 zs
->next_out
= stream
->buffer
;
226 zs
->avail_out
= BUFFER_SIZE
;
228 status
= deflate (stream
->stream
, Z_NO_FLUSH
);
229 if (status
!= Z_OK
&& status
!= Z_STREAM_END
)
232 if (zs
->avail_out
== 0) {
233 n
= write_to_managed (stream
);