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, write to the
18 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 * Author: Shaun McCance <shaunm@gnome.org>
26 #include <glib/gi18n.h>
29 #include "yelp-magic-decompressor.h"
32 #include "yelp-bz2-decompressor.h"
36 #include "yelp-lzma-decompressor.h"
40 static void yelp_magic_decompressor_iface_init (GConverterIface
*iface
);
42 struct _YelpMagicDecompressor
44 GObject parent_instance
;
46 GConverter
*magic_decoder_ring
;
51 G_DEFINE_TYPE_WITH_CODE (YelpMagicDecompressor
, yelp_magic_decompressor
, G_TYPE_OBJECT
,
52 G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER
,
53 yelp_magic_decompressor_iface_init
))
56 yelp_magic_decompressor_dispose (GObject
*object
)
58 YelpMagicDecompressor
*decompressor
= YELP_MAGIC_DECOMPRESSOR (object
);
60 if (decompressor
->magic_decoder_ring
) {
61 g_object_unref (decompressor
->magic_decoder_ring
);
62 decompressor
->magic_decoder_ring
= NULL
;
65 G_OBJECT_CLASS (yelp_magic_decompressor_parent_class
)->dispose (object
);
69 yelp_magic_decompressor_init (YelpMagicDecompressor
*decompressor
)
71 decompressor
->magic_decoder_ring
= NULL
;
72 decompressor
->first
= TRUE
;
76 yelp_magic_decompressor_class_init (YelpMagicDecompressorClass
*klass
)
78 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
80 gobject_class
->dispose
= yelp_magic_decompressor_dispose
;
83 YelpMagicDecompressor
*
84 yelp_magic_decompressor_new (void)
86 YelpMagicDecompressor
*decompressor
;
88 decompressor
= g_object_new (YELP_TYPE_MAGIC_DECOMPRESSOR
, NULL
);
94 yelp_magic_decompressor_reset (GConverter
*converter
)
96 YelpMagicDecompressor
*decompressor
= YELP_MAGIC_DECOMPRESSOR (converter
);
98 if (decompressor
->magic_decoder_ring
)
99 g_converter_reset (decompressor
->magic_decoder_ring
);
103 yelp_magic_decompressor_choose (const void *inbuf
, gsize inbuf_size
)
105 /* If input_size is less than two the first time, we end up
106 * not getting detection. Might be worth addressing. Not
109 * The two-byte magic we're doing here is not sufficient in
110 * the general case. It is sufficient for the specific data
117 if (((gchar
*) inbuf
)[0] == 'B' && ((gchar
*) inbuf
)[1] == 'Z') {
118 return (GConverter
*) yelp_bz2_decompressor_new ();
122 if (((gchar
*) inbuf
)[0] == ']' && ((gchar
*) inbuf
)[1] == '\0') {
123 return (GConverter
*) yelp_lzma_decompressor_new ();
126 if (((guint8
*) inbuf
)[0] == 0x1F && ((guint8
*) inbuf
)[1] == 0x8B) {
127 return (GConverter
*) g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP
);
133 static GConverterResult
134 yelp_magic_decompressor_convert (GConverter
*converter
,
139 GConverterFlags flags
,
141 gsize
*bytes_written
,
144 YelpMagicDecompressor
*decompressor
;
147 decompressor
= YELP_MAGIC_DECOMPRESSOR (converter
);
149 if (decompressor
->first
) {
150 decompressor
->magic_decoder_ring
=
151 yelp_magic_decompressor_choose (inbuf
, inbuf_size
);
152 decompressor
->first
= FALSE
;
155 if (decompressor
->magic_decoder_ring
) {
156 return g_converter_convert (decompressor
->magic_decoder_ring
,
160 bytes_read
, bytes_written
,
164 /* If there's no magic_decoder_ring, we just copy the data
165 * straight through. */
166 txfer_size
= MIN (inbuf_size
, outbuf_size
);
167 memcpy (outbuf
, inbuf
, txfer_size
);
168 *bytes_read
= txfer_size
;
169 *bytes_written
= txfer_size
;
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
;