gio/: fully remove gioalias hacks
[platform/upstream/glib.git] / gio / gzlibdecompressor.c
1 /* GIO - GLib Input, Output and Streaming Library
2  *
3  * Copyright (C) 2009 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include "config.h"
24
25 #include "gzlibdecompressor.h"
26
27 #include <errno.h>
28 #include <zlib.h>
29 #include <string.h>
30
31 #include "gioerror.h"
32 #include "gioenums.h"
33 #include "gioenumtypes.h"
34 #include "glibintl.h"
35
36
37 enum {
38   PROP_0,
39   PROP_FORMAT
40 };
41
42 /**
43  * SECTION:gzdecompressor
44  * @short_description: Zlib decompressor
45  * @include: gio/gio.h
46  *
47  * #GZlibDecompressor is an implementation of #GConverter that
48  * decompresses data compressed with zlib.
49  */
50
51 static void g_zlib_decompressor_iface_init          (GConverterIface *iface);
52
53 /**
54  * GZlibDecompressor:
55  *
56  * Zlib decompression
57  */
58 struct _GZlibDecompressor
59 {
60   GObject parent_instance;
61
62   GZlibCompressorFormat format;
63   z_stream zstream;
64 };
65
66 G_DEFINE_TYPE_WITH_CODE (GZlibDecompressor, g_zlib_decompressor, G_TYPE_OBJECT,
67                          G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
68                                                 g_zlib_decompressor_iface_init))
69
70 static void
71 g_zlib_decompressor_finalize (GObject *object)
72 {
73   GZlibDecompressor *decompressor;
74
75   decompressor = G_ZLIB_DECOMPRESSOR (object);
76
77   inflateEnd (&decompressor->zstream);
78
79   G_OBJECT_CLASS (g_zlib_decompressor_parent_class)->finalize (object);
80 }
81
82
83 static void
84 g_zlib_decompressor_set_property (GObject      *object,
85                                   guint         prop_id,
86                                   const GValue *value,
87                                   GParamSpec   *pspec)
88 {
89   GZlibDecompressor *decompressor;
90
91   decompressor = G_ZLIB_DECOMPRESSOR (object);
92
93   switch (prop_id)
94     {
95     case PROP_FORMAT:
96       decompressor->format = g_value_get_enum (value);
97       break;
98
99     default:
100       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101       break;
102     }
103
104 }
105
106 static void
107 g_zlib_decompressor_get_property (GObject    *object,
108                                   guint       prop_id,
109                                   GValue     *value,
110                                   GParamSpec *pspec)
111 {
112   GZlibDecompressor *decompressor;
113
114   decompressor = G_ZLIB_DECOMPRESSOR (object);
115
116   switch (prop_id)
117     {
118     case PROP_FORMAT:
119       g_value_set_enum (value, decompressor->format);
120       break;
121
122     default:
123       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124       break;
125     }
126 }
127
128 static void
129 g_zlib_decompressor_init (GZlibDecompressor *decompressor)
130 {
131 }
132
133 static void
134 g_zlib_decompressor_constructed (GObject *object)
135 {
136   GZlibDecompressor *decompressor;
137   int res;
138
139   decompressor = G_ZLIB_DECOMPRESSOR (object);
140
141   if (decompressor->format == G_ZLIB_COMPRESSOR_FORMAT_GZIP)
142     {
143       /* + 16 for gzip */
144       res = inflateInit2 (&decompressor->zstream, MAX_WBITS + 16);
145     }
146   else if (decompressor->format == G_ZLIB_COMPRESSOR_FORMAT_RAW)
147     {
148       /* Negative for gzip */
149       res = inflateInit2 (&decompressor->zstream, -MAX_WBITS);
150     }
151   else /* ZLIB */
152     res = inflateInit (&decompressor->zstream);
153
154   if (res == Z_MEM_ERROR )
155     g_error ("GZlibDecompressor: Not enough memory for zlib use");
156
157   if (res != Z_OK)
158     g_warning ("unexpected zlib error: %s\n", decompressor->zstream.msg);
159 }
160
161 static void
162 g_zlib_decompressor_class_init (GZlibDecompressorClass *klass)
163 {
164   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
165
166   gobject_class->finalize = g_zlib_decompressor_finalize;
167   gobject_class->constructed = g_zlib_decompressor_constructed;
168   gobject_class->get_property = g_zlib_decompressor_get_property;
169   gobject_class->set_property = g_zlib_decompressor_set_property;
170
171   g_object_class_install_property (gobject_class,
172                                    PROP_FORMAT,
173                                    g_param_spec_enum ("format",
174                                                       P_("compression format"),
175                                                       P_("The format of the compressed data"),
176                                                       G_TYPE_ZLIB_COMPRESSOR_FORMAT,
177                                                       G_ZLIB_COMPRESSOR_FORMAT_ZLIB,
178                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
179                                                       G_PARAM_STATIC_STRINGS));
180 }
181
182 /**
183  * g_zlib_decompressor_new:
184  * @format: The format to use for the compressed data
185  *
186  * Creates a new #GZlibDecompressor.
187  *
188  * Returns: a new #GZlibDecompressor
189  *
190  * Since: 2.24
191  **/
192 GZlibDecompressor *
193 g_zlib_decompressor_new (GZlibCompressorFormat format)
194 {
195   GZlibDecompressor *decompressor;
196
197   decompressor = g_object_new (G_TYPE_ZLIB_DECOMPRESSOR,
198                                "format", format,
199                                NULL);
200
201   return decompressor;
202 }
203
204 static void
205 g_zlib_decompressor_reset (GConverter *converter)
206 {
207   GZlibDecompressor *decompressor = G_ZLIB_DECOMPRESSOR (converter);
208   int res;
209
210   res = inflateReset (&decompressor->zstream);
211   if (res != Z_OK)
212     g_warning ("unexpected zlib error: %s\n", decompressor->zstream.msg);
213 }
214
215 static GConverterResult
216 g_zlib_decompressor_convert (GConverter *converter,
217                              const void *inbuf,
218                              gsize       inbuf_size,
219                              void       *outbuf,
220                              gsize       outbuf_size,
221                              GConverterFlags flags,
222                              gsize      *bytes_read,
223                              gsize      *bytes_written,
224                              GError    **error)
225 {
226   GZlibDecompressor *decompressor;
227   int res;
228
229   decompressor = G_ZLIB_DECOMPRESSOR (converter);
230
231   decompressor->zstream.next_in = (void *)inbuf;
232   decompressor->zstream.avail_in = inbuf_size;
233
234   decompressor->zstream.next_out = outbuf;
235   decompressor->zstream.avail_out = outbuf_size;
236
237   res = inflate (&decompressor->zstream, Z_NO_FLUSH);
238
239   if (res == Z_DATA_ERROR || res == Z_NEED_DICT)
240     {
241       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
242                            _("Invalid compressed data"));
243       return G_CONVERTER_ERROR;
244     }
245
246   if (res == Z_MEM_ERROR)
247     {
248       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
249                            _("Not enough memory"));
250       return G_CONVERTER_ERROR;
251     }
252
253     if (res == Z_STREAM_ERROR)
254     {
255       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
256                    _("Internal error: %s"), decompressor->zstream.msg);
257       return G_CONVERTER_ERROR;
258     }
259
260     if (res == Z_BUF_ERROR)
261       {
262         if (flags & G_CONVERTER_FLUSH)
263           return G_CONVERTER_FLUSHED;
264
265         /* Z_FINISH not set, so this means no progress could be made */
266         /* We do have output space, so this should only happen if we
267            have no input but need some */
268
269         g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT,
270                              _("Need more input"));
271         return G_CONVERTER_ERROR;
272       }
273
274   if (res == Z_OK || res == Z_STREAM_END)
275     {
276       *bytes_read = inbuf_size - decompressor->zstream.avail_in;
277       *bytes_written = outbuf_size - decompressor->zstream.avail_out;
278
279       if (res == Z_STREAM_END)
280         return G_CONVERTER_FINISHED;
281       return G_CONVERTER_CONVERTED;
282     }
283
284   g_assert_not_reached ();
285 }
286
287 static void
288 g_zlib_decompressor_iface_init (GConverterIface *iface)
289 {
290   iface->convert = g_zlib_decompressor_convert;
291   iface->reset = g_zlib_decompressor_reset;
292 }