1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * Copyright (C) 2009 Red Hat, Inc.
4 * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 * Author: Shaun McCance <shaunm@gnome.org>
24 #include <glib/gi18n.h>
27 #include "yelp-magic-decompressor.h"
30 #include "yelp-bz2-decompressor.h"
34 #include "yelp-lzma-decompressor.h"
38 static void yelp_magic_decompressor_iface_init (GConverterIface
*iface
);
40 struct _YelpMagicDecompressor
42 GObject parent_instance
;
44 GConverter
*magic_decoder_ring
;
49 G_DEFINE_TYPE_WITH_CODE (YelpMagicDecompressor
, yelp_magic_decompressor
, G_TYPE_OBJECT
,
50 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER
,
51 yelp_magic_decompressor_iface_init
))
54 yelp_magic_decompressor_dispose (GObject
*object
)
56 YelpMagicDecompressor
*decompressor
= YELP_MAGIC_DECOMPRESSOR (object
);
58 if (decompressor
->magic_decoder_ring
) {
59 g_object_unref (decompressor
->magic_decoder_ring
);
60 decompressor
->magic_decoder_ring
= NULL
;
63 G_OBJECT_CLASS (yelp_magic_decompressor_parent_class
)->dispose (object
);
67 yelp_magic_decompressor_init (YelpMagicDecompressor
*decompressor
)
69 decompressor
->magic_decoder_ring
= NULL
;
70 decompressor
->first
= TRUE
;
74 yelp_magic_decompressor_class_init (YelpMagicDecompressorClass
*klass
)
76 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
78 gobject_class
->dispose
= yelp_magic_decompressor_dispose
;
81 YelpMagicDecompressor
*
82 yelp_magic_decompressor_new (void)
84 YelpMagicDecompressor
*decompressor
;
86 decompressor
= g_object_new (YELP_TYPE_MAGIC_DECOMPRESSOR
, NULL
);
92 yelp_magic_decompressor_reset (GConverter
*converter
)
94 YelpMagicDecompressor
*decompressor
= YELP_MAGIC_DECOMPRESSOR (converter
);
96 if (decompressor
->magic_decoder_ring
)
97 g_converter_reset (decompressor
->magic_decoder_ring
);
101 yelp_magic_decompressor_choose (const void *inbuf
, gsize inbuf_size
)
103 /* If input_size is less than two the first time, we end up
104 * not getting detection. Might be worth addressing. Not
107 * The two-byte magic we're doing here is not sufficient in
108 * the general case. It is sufficient for the specific data
115 if (((gchar
*) inbuf
)[0] == 'B' && ((gchar
*) inbuf
)[1] == 'Z') {
116 return (GConverter
*) yelp_bz2_decompressor_new ();
120 if (((gchar
*) inbuf
)[0] == ']' && ((gchar
*) inbuf
)[1] == '\0') {
121 return (GConverter
*) yelp_lzma_decompressor_new ();
124 if (((guint8
*) inbuf
)[0] == 0x1F && ((guint8
*) inbuf
)[1] == 0x8B) {
125 return (GConverter
*) g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP
);
131 static GConverterResult
132 yelp_magic_decompressor_convert (GConverter
*converter
,
137 GConverterFlags flags
,
139 gsize
*bytes_written
,
142 YelpMagicDecompressor
*decompressor
;
145 decompressor
= YELP_MAGIC_DECOMPRESSOR (converter
);
147 if (decompressor
->first
) {
148 decompressor
->magic_decoder_ring
=
149 yelp_magic_decompressor_choose (inbuf
, inbuf_size
);
150 decompressor
->first
= FALSE
;
153 if (decompressor
->magic_decoder_ring
) {
154 return g_converter_convert (decompressor
->magic_decoder_ring
,
158 bytes_read
, bytes_written
,
162 /* If there's no magic_decoder_ring, we just copy the data
163 * straight through. */
164 txfer_size
= MIN (inbuf_size
, outbuf_size
);
165 memcpy (outbuf
, inbuf
, txfer_size
);
166 *bytes_read
= txfer_size
;
167 *bytes_written
= txfer_size
;
169 if (flags
& G_CONVERTER_INPUT_AT_END
)
170 return G_CONVERTER_FINISHED
;
171 return G_CONVERTER_CONVERTED
;
175 yelp_magic_decompressor_iface_init (GConverterIface
*iface
)
177 iface
->convert
= yelp_magic_decompressor_convert
;
178 iface
->reset
= yelp_magic_decompressor_reset
;