Update Chinese (China) translation
[yelp.git] / libyelp / yelp-magic-decompressor.c
blob5e7b493f46bc758c78021ff8a1d6495cb974b022
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include "config.h"
24 #include <glib/gi18n.h>
25 #include <string.h>
27 #include "yelp-magic-decompressor.h"
29 #ifdef ENABLE_BZ2
30 #include "yelp-bz2-decompressor.h"
31 #endif
33 #ifdef ENABLE_LZMA
34 #include "yelp-lzma-decompressor.h"
35 #endif
38 static void yelp_magic_decompressor_iface_init (GConverterIface *iface);
40 struct _YelpMagicDecompressor
42 GObject parent_instance;
44 GConverter *magic_decoder_ring;
46 gboolean first;
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))
53 static void
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);
66 static void
67 yelp_magic_decompressor_init (YelpMagicDecompressor *decompressor)
69 decompressor->magic_decoder_ring = NULL;
70 decompressor->first = TRUE;
73 static void
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);
88 return decompressor;
91 static void
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);
100 static GConverter*
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
105 * sure I care.
107 * The two-byte magic we're doing here is not sufficient in
108 * the general case. It is sufficient for the specific data
109 * Yelp deals with.
111 if (inbuf_size <= 2)
112 return NULL;
114 #ifdef ENABLE_BZ2
115 if (((gchar *) inbuf)[0] == 'B' && ((gchar *) inbuf)[1] == 'Z') {
116 return (GConverter *) yelp_bz2_decompressor_new ();
118 #endif
119 #ifdef ENABLE_LZMA
120 if (((gchar *) inbuf)[0] == ']' && ((gchar *) inbuf)[1] == '\0') {
121 return (GConverter *) yelp_lzma_decompressor_new ();
123 #endif
124 if (((guint8*) inbuf)[0] == 0x1F && ((guint8*) inbuf)[1] == 0x8B) {
125 return (GConverter *) g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
128 return NULL;
131 static GConverterResult
132 yelp_magic_decompressor_convert (GConverter *converter,
133 const void *inbuf,
134 gsize inbuf_size,
135 void *outbuf,
136 gsize outbuf_size,
137 GConverterFlags flags,
138 gsize *bytes_read,
139 gsize *bytes_written,
140 GError **error)
142 YelpMagicDecompressor *decompressor;
143 gsize txfer_size;
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,
155 inbuf, inbuf_size,
156 outbuf, outbuf_size,
157 flags,
158 bytes_read, bytes_written,
159 error);
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;
174 static void
175 yelp_magic_decompressor_iface_init (GConverterIface *iface)
177 iface->convert = yelp_magic_decompressor_convert;
178 iface->reset = yelp_magic_decompressor_reset;