summaryrefslogtreecommitdiff
path: root/libyelp
diff options
context:
space:
mode:
authorShaun McCance <shaunm@gnome.org>2010-04-26 11:24:17 -0500
committerShaun McCance <shaunm@gnome.org>2010-04-26 11:24:17 -0500
commitcd6e6383aba8e93f983e298e6044164e0fc19cab (patch)
tree9db9a546bcbd705f69d3df6cd3912a616d8d1594 /libyelp
parentfeed213d5298125b026bc0c74d4b3be922b65e0e (diff)
downloadyelp-cd6e6383aba8e93f983e298e6044164e0fc19cab.tar.gz
[libyelp] Adding GIO decompressors for bz2, lzma, and magic
Diffstat (limited to 'libyelp')
-rw-r--r--libyelp/Makefile.am14
-rw-r--r--libyelp/yelp-bz2-decompressor.c173
-rw-r--r--libyelp/yelp-bz2-decompressor.h53
-rw-r--r--libyelp/yelp-lzma-decompressor.c174
-rw-r--r--libyelp/yelp-lzma-decompressor.h53
-rw-r--r--libyelp/yelp-magic-decompressor.c147
-rw-r--r--libyelp/yelp-magic-decompressor.h52
7 files changed, 662 insertions, 4 deletions
diff --git a/libyelp/Makefile.am b/libyelp/Makefile.am
index 56a6595d..770ce02d 100644
--- a/libyelp/Makefile.am
+++ b/libyelp/Makefile.am
@@ -1,12 +1,15 @@
lib_LTLIBRARIES = libyelp.la
libyelp_la_SOURCES = \
+ yelp-bz2-decompressor.c \
yelp-debug.c \
yelp-error.c \
yelp-docbook-document.c \
yelp-document.c \
yelp-io-channel.c \
yelp-location-entry.c \
+ yelp-lzma-decompressor.c \
+ yelp-magic-decompressor.c \
yelp-mallard-document.c \
yelp-marshal.c \
yelp-settings.c \
@@ -48,10 +51,13 @@ BUILT_SOURCES = \
yelp-types.c \
yelp-types.h
-EXTRA_DIST = \
- yelp-debug.h \
- yelp-error.h \
- yelp-io-channel.h \
+EXTRA_DIST = \
+ yelp-bz2-decompressor.h \
+ yelp-debug.h \
+ yelp-error.h \
+ yelp-io-channel.h \
+ yelp-lzma-decompressor.h \
+ yelp-magic-decompressor.h \
yelp-marshal.list
yelp-marshal.h: stamp-yelp-marshal.h
diff --git a/libyelp/yelp-bz2-decompressor.c b/libyelp/yelp-bz2-decompressor.c
new file mode 100644
index 00000000..98802cee
--- /dev/null
+++ b/libyelp/yelp-bz2-decompressor.c
@@ -0,0 +1,173 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include "yelp-bz2-decompressor.h"
+
+static void yelp_bz2_decompressor_iface_init (GConverterIface *iface);
+
+struct _YelpBz2Decompressor
+{
+ GObject parent_instance;
+
+ bz_stream bzstream;
+};
+
+G_DEFINE_TYPE_WITH_CODE (YelpBz2Decompressor, yelp_bz2_decompressor, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
+ yelp_bz2_decompressor_iface_init))
+
+static void
+yelp_bz2_decompressor_finalize (GObject *object)
+{
+ YelpBz2Decompressor *decompressor;
+
+ decompressor = YELP_BZ2_DECOMPRESSOR (object);
+
+ BZ2_bzDecompressEnd (&decompressor->bzstream);
+
+ G_OBJECT_CLASS (yelp_bz2_decompressor_parent_class)->finalize (object);
+}
+
+static void
+yelp_bz2_decompressor_init (YelpBz2Decompressor *decompressor)
+{
+}
+
+static void
+yelp_bz2_decompressor_constructed (GObject *object)
+{
+ YelpBz2Decompressor *decompressor;
+ int res;
+
+ decompressor = YELP_BZ2_DECOMPRESSOR (object);
+
+ res = BZ2_bzDecompressInit (&decompressor->bzstream, 0, FALSE);
+
+ if (res == BZ_MEM_ERROR )
+ g_error ("YelpBz2Decompressor: Not enough memory for bzip2 use");
+
+ if (res != BZ_OK)
+ g_error ("YelpBz2Decompressor: Unexpected bzip2 error");
+}
+
+static void
+yelp_bz2_decompressor_class_init (YelpBz2DecompressorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = yelp_bz2_decompressor_finalize;
+ gobject_class->constructed = yelp_bz2_decompressor_constructed;
+}
+
+YelpBz2Decompressor *
+yelp_bz2_decompressor_new (void)
+{
+ YelpBz2Decompressor *decompressor;
+
+ decompressor = g_object_new (YELP_TYPE_BZ2_DECOMPRESSOR, NULL);
+
+ return decompressor;
+}
+
+static void
+yelp_bz2_decompressor_reset (GConverter *converter)
+{
+ YelpBz2Decompressor *decompressor = YELP_BZ2_DECOMPRESSOR (converter);
+ int res;
+
+ /* libbzip2 doesn't have a reset function. Ending and reiniting
+ * might do the trick. But this is untested. If reset matters
+ * to you, test this.
+ */
+ BZ2_bzDecompressEnd (&decompressor->bzstream);
+ res = BZ2_bzDecompressInit (&decompressor->bzstream, 0, FALSE);
+
+ if (res == BZ_MEM_ERROR )
+ g_error ("YelpBz2Decompressor: Not enough memory for bzip2 use");
+
+ if (res != BZ_OK)
+ g_error ("YelpBz2Decompressor: Unexpected bzip2 error");
+}
+
+static GConverterResult
+yelp_bz2_decompressor_convert (GConverter *converter,
+ const void *inbuf,
+ gsize inbuf_size,
+ void *outbuf,
+ gsize outbuf_size,
+ GConverterFlags flags,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ GError **error)
+{
+ YelpBz2Decompressor *decompressor;
+ gsize header_size;
+ int res;
+
+ decompressor = YELP_BZ2_DECOMPRESSOR (converter);
+
+ decompressor->bzstream.next_in = (void *)inbuf;
+ decompressor->bzstream.avail_in = inbuf_size;
+
+ decompressor->bzstream.next_out = outbuf;
+ decompressor->bzstream.avail_out = outbuf_size;
+
+ res = BZ2_bzDecompress (&decompressor->bzstream);
+
+ if (res == BZ_DATA_ERROR || res == BZ_DATA_ERROR_MAGIC) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+ _("Invalid compressed data"));
+ return G_CONVERTER_ERROR;
+ }
+
+ if (res == BZ_MEM_ERROR) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Not enough memory"));
+ return G_CONVERTER_ERROR;
+ }
+
+ if (res == BZ_OK || res == BZ_STREAM_END) {
+ *bytes_read = inbuf_size - decompressor->bzstream.avail_in;
+ *bytes_written = outbuf_size - decompressor->bzstream.avail_out;
+
+ if (res == BZ_STREAM_END)
+ return G_CONVERTER_FINISHED;
+ return G_CONVERTER_CONVERTED;
+ }
+
+ g_assert_not_reached ();
+}
+
+static void
+yelp_bz2_decompressor_iface_init (GConverterIface *iface)
+{
+ iface->convert = yelp_bz2_decompressor_convert;
+ iface->reset = yelp_bz2_decompressor_reset;
+}
diff --git a/libyelp/yelp-bz2-decompressor.h b/libyelp/yelp-bz2-decompressor.h
new file mode 100644
index 00000000..e067f26e
--- /dev/null
+++ b/libyelp/yelp-bz2-decompressor.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_BZ2_DECOMPRESSOR_H__
+#define __YELP_BZ2_DECOMPRESSOR_H__
+
+#include <gio/gio.h>
+#include <bzlib.h>
+
+G_BEGIN_DECLS
+
+#define YELP_TYPE_BZ2_DECOMPRESSOR (yelp_bz2_decompressor_get_type ())
+#define YELP_BZ2_DECOMPRESSOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_BZ2_DECOMPRESSOR, YelpBz2Decompressor))
+#define YELP_BZ2_DECOMPRESSOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), YELP_TYPE_BZ2_DECOMPRESSOR, YelpBz2DecompressorClass))
+#define YELP_IS_BZ2_DECOMPRESSOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_BZ2_DECOMPRESSOR))
+#define YELP_IS_BZ2_DECOMPRESSOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_BZ2_DECOMPRESSOR))
+#define YELP_BZ2_DECOMPRESSOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_BZ2_DECOMPRESSOR, YelpBz2DecompressorClass))
+
+typedef struct _YelpBz2Decompressor YelpBz2Decompressor;
+typedef struct _YelpBz2DecompressorClass YelpBz2DecompressorClass;
+
+struct _YelpBz2DecompressorClass
+{
+ GObjectClass parent_class;
+};
+
+GType yelp_bz2_decompressor_get_type (void);
+
+YelpBz2Decompressor *yelp_bz2_decompressor_new (void);
+
+G_END_DECLS
+
+#endif /* __YELP_BZ2_DECOMPRESSOR_H__ */
diff --git a/libyelp/yelp-lzma-decompressor.c b/libyelp/yelp-lzma-decompressor.c
new file mode 100644
index 00000000..1bd38ef6
--- /dev/null
+++ b/libyelp/yelp-lzma-decompressor.c
@@ -0,0 +1,174 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include "yelp-lzma-decompressor.h"
+
+static void yelp_lzma_decompressor_iface_init (GConverterIface *iface);
+
+struct _YelpLzmaDecompressor
+{
+ GObject parent_instance;
+
+ lzmadec_stream lzmastream;
+};
+
+G_DEFINE_TYPE_WITH_CODE (YelpLzmaDecompressor, yelp_lzma_decompressor, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
+ yelp_lzma_decompressor_iface_init))
+
+static void
+yelp_lzma_decompressor_finalize (GObject *object)
+{
+ YelpLzmaDecompressor *decompressor;
+
+ decompressor = YELP_LZMA_DECOMPRESSOR (object);
+
+ lzmadec_end (&decompressor->lzmastream);
+
+ G_OBJECT_CLASS (yelp_lzma_decompressor_parent_class)->finalize (object);
+}
+
+static void
+yelp_lzma_decompressor_init (YelpLzmaDecompressor *decompressor)
+{
+}
+
+static void
+yelp_lzma_decompressor_constructed (GObject *object)
+{
+ YelpLzmaDecompressor *decompressor;
+ int res;
+
+ decompressor = YELP_LZMA_DECOMPRESSOR (object);
+
+ res = lzmadec_init (&decompressor->lzmastream);
+
+ if (res == LZMADEC_MEM_ERROR )
+ g_error ("YelpLzmaDecompressor: Not enough memory for lzma use");
+
+ if (res != LZMADEC_OK)
+ g_error ("YelpLzmaDecompressor: Unexpected lzma error");
+}
+
+static void
+yelp_lzma_decompressor_class_init (YelpLzmaDecompressorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = yelp_lzma_decompressor_finalize;
+ gobject_class->constructed = yelp_lzma_decompressor_constructed;
+}
+
+YelpLzmaDecompressor *
+yelp_lzma_decompressor_new (void)
+{
+ YelpLzmaDecompressor *decompressor;
+
+ decompressor = g_object_new (YELP_TYPE_LZMA_DECOMPRESSOR, NULL);
+
+ return decompressor;
+}
+
+static void
+yelp_lzma_decompressor_reset (GConverter *converter)
+{
+ YelpLzmaDecompressor *decompressor = YELP_LZMA_DECOMPRESSOR (converter);
+ int res;
+
+ /* lzmadec doesn't have a reset function. Ending and reiniting
+ * might do the trick. But this is untested. If reset matters
+ * to you, test this.
+ */
+ lzmadec_end (&decompressor->lzmastream);
+ res = lzmadec_init (&decompressor->lzmastream);
+
+ if (res == LZMADEC_MEM_ERROR )
+ g_error ("YelpLzmaDecompressor: Not enough memory for lzma use");
+
+ if (res != LZMADEC_OK)
+ g_error ("YelpLzmaDecompressor: Unexpected lzma error");
+}
+
+static GConverterResult
+yelp_lzma_decompressor_convert (GConverter *converter,
+ const void *inbuf,
+ gsize inbuf_size,
+ void *outbuf,
+ gsize outbuf_size,
+ GConverterFlags flags,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ GError **error)
+{
+ YelpLzmaDecompressor *decompressor;
+ gsize header_size;
+ int res;
+
+ decompressor = YELP_LZMA_DECOMPRESSOR (converter);
+
+ decompressor->lzmastream.next_in = (void *)inbuf;
+ decompressor->lzmastream.avail_in = inbuf_size;
+
+ decompressor->lzmastream.next_out = outbuf;
+ decompressor->lzmastream.avail_out = outbuf_size;
+
+ res = lzmadec_decode (&decompressor->lzmastream,
+ flags & G_CONVERTER_INPUT_AT_END);
+
+ if (res == LZMADEC_DATA_ERROR || res == LZMADEC_HEADER_ERROR) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+ _("Invalid compressed data"));
+ return G_CONVERTER_ERROR;
+ }
+
+ if (res == LZMADEC_MEM_ERROR) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Not enough memory"));
+ return G_CONVERTER_ERROR;
+ }
+
+ if (res == LZMADEC_OK || res == LZMADEC_STREAM_END) {
+ *bytes_read = inbuf_size - decompressor->lzmastream.avail_in;
+ *bytes_written = outbuf_size - decompressor->lzmastream.avail_out;
+
+ if (res == LZMADEC_STREAM_END)
+ return G_CONVERTER_FINISHED;
+ return G_CONVERTER_CONVERTED;
+ }
+
+ g_assert_not_reached ();
+}
+
+static void
+yelp_lzma_decompressor_iface_init (GConverterIface *iface)
+{
+ iface->convert = yelp_lzma_decompressor_convert;
+ iface->reset = yelp_lzma_decompressor_reset;
+}
diff --git a/libyelp/yelp-lzma-decompressor.h b/libyelp/yelp-lzma-decompressor.h
new file mode 100644
index 00000000..f47cf2b3
--- /dev/null
+++ b/libyelp/yelp-lzma-decompressor.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_LZMA_DECOMPRESSOR_H__
+#define __YELP_LZMA_DECOMPRESSOR_H__
+
+#include <gio/gio.h>
+#include <lzmadec.h>
+
+G_BEGIN_DECLS
+
+#define YELP_TYPE_LZMA_DECOMPRESSOR (yelp_lzma_decompressor_get_type ())
+#define YELP_LZMA_DECOMPRESSOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_LZMA_DECOMPRESSOR, YelpLzmaDecompressor))
+#define YELP_LZMA_DECOMPRESSOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), YELP_TYPE_LZMA_DECOMPRESSOR, YelpLzmaDecompressorClass))
+#define YELP_IS_LZMA_DECOMPRESSOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_LZMA_DECOMPRESSOR))
+#define YELP_IS_LZMA_DECOMPRESSOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_LZMA_DECOMPRESSOR))
+#define YELP_LZMA_DECOMPRESSOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_LZMA_DECOMPRESSOR, YelpLzmaDecompressorClass))
+
+typedef struct _YelpLzmaDecompressor YelpLzmaDecompressor;
+typedef struct _YelpLzmaDecompressorClass YelpLzmaDecompressorClass;
+
+struct _YelpLzmaDecompressorClass
+{
+ GObjectClass parent_class;
+};
+
+GType yelp_lzma_decompressor_get_type (void);
+
+YelpLzmaDecompressor *yelp_lzma_decompressor_new (void);
+
+G_END_DECLS
+
+#endif /* __YELP_LZMA_DECOMPRESSOR_H__ */
diff --git a/libyelp/yelp-magic-decompressor.c b/libyelp/yelp-magic-decompressor.c
new file mode 100644
index 00000000..cf1b09bc
--- /dev/null
+++ b/libyelp/yelp-magic-decompressor.c
@@ -0,0 +1,147 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "yelp-bz2-decompressor.h"
+#include "yelp-lzma-decompressor.h"
+#include "yelp-magic-decompressor.h"
+
+static void yelp_magic_decompressor_iface_init (GConverterIface *iface);
+
+struct _YelpMagicDecompressor
+{
+ GObject parent_instance;
+
+ GConverter *magic_decoder_ring;
+
+ gboolean first;
+};
+
+G_DEFINE_TYPE_WITH_CODE (YelpMagicDecompressor, yelp_magic_decompressor, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
+ yelp_magic_decompressor_iface_init))
+
+static void
+yelp_magic_decompressor_dispose (GObject *object)
+{
+ YelpMagicDecompressor *decompressor;
+
+ g_object_unref (decompressor->magic_decoder_ring);
+
+ G_OBJECT_CLASS (yelp_magic_decompressor_parent_class)->dispose (object);
+}
+
+static void
+yelp_magic_decompressor_init (YelpMagicDecompressor *decompressor)
+{
+ decompressor->magic_decoder_ring = NULL;
+ decompressor->first = TRUE;
+}
+
+static void
+yelp_magic_decompressor_class_init (YelpMagicDecompressorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = yelp_magic_decompressor_dispose;
+}
+
+YelpMagicDecompressor *
+yelp_magic_decompressor_new (void)
+{
+ YelpMagicDecompressor *decompressor;
+
+ decompressor = g_object_new (YELP_TYPE_MAGIC_DECOMPRESSOR, NULL);
+
+ return decompressor;
+}
+
+static void
+yelp_magic_decompressor_reset (GConverter *converter)
+{
+ YelpMagicDecompressor *decompressor = YELP_MAGIC_DECOMPRESSOR (converter);
+
+ if (decompressor->magic_decoder_ring)
+ g_converter_reset (decompressor->magic_decoder_ring);
+}
+
+static GConverterResult
+yelp_magic_decompressor_convert (GConverter *converter,
+ const void *inbuf,
+ gsize inbuf_size,
+ void *outbuf,
+ gsize outbuf_size,
+ GConverterFlags flags,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ GError **error)
+{
+ YelpMagicDecompressor *decompressor;
+
+ decompressor = YELP_MAGIC_DECOMPRESSOR (converter);
+
+ if (decompressor->first) {
+ decompressor->first = FALSE;
+ /* If input_size is less than two the first time, we end up
+ * not getting detection. Might be worth addressing. Not
+ * sure I care.
+ *
+ * The two-byte magic we're doing here is not sufficient in
+ * the general case. It is sufficient for the specific data
+ * Yelp deals with.
+ */
+ if (inbuf_size <= 2)
+ ;
+ else if (((gchar *) inbuf)[0] == 'B' &&
+ ((gchar *) inbuf)[1] == 'Z') {
+ decompressor->magic_decoder_ring = (GConverter *) yelp_bz2_decompressor_new ();
+ }
+ else if (((gchar *) inbuf)[0] == ']' &&
+ ((gchar *) inbuf)[1] == '\0') {
+ decompressor->magic_decoder_ring = (GConverter *) yelp_lzma_decompressor_new ();
+ }
+ else {
+ decompressor->magic_decoder_ring =
+ (GConverter *) g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
+ }
+ }
+
+ return g_converter_convert (decompressor->magic_decoder_ring,
+ inbuf, inbuf_size,
+ outbuf, outbuf_size,
+ flags,
+ bytes_read, bytes_written,
+ error);
+
+ g_assert_not_reached ();
+}
+
+static void
+yelp_magic_decompressor_iface_init (GConverterIface *iface)
+{
+ iface->convert = yelp_magic_decompressor_convert;
+ iface->reset = yelp_magic_decompressor_reset;
+}
diff --git a/libyelp/yelp-magic-decompressor.h b/libyelp/yelp-magic-decompressor.h
new file mode 100644
index 00000000..15c09bbd
--- /dev/null
+++ b/libyelp/yelp-magic-decompressor.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ * Copyright (C) 2009 Shaun McCance <shaunm@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm@gnome.org>
+ */
+
+#ifndef __YELP_MAGIC_DECOMPRESSOR_H__
+#define __YELP_MAGIC_DECOMPRESSOR_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define YELP_TYPE_MAGIC_DECOMPRESSOR (yelp_magic_decompressor_get_type ())
+#define YELP_MAGIC_DECOMPRESSOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), YELP_TYPE_MAGIC_DECOMPRESSOR, YelpMagicDecompressor))
+#define YELP_MAGIC_DECOMPRESSOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), YELP_TYPE_MAGIC_DECOMPRESSOR, YelpMagicDecompressorClass))
+#define YELP_IS_MAGIC_DECOMPRESSOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), YELP_TYPE_MAGIC_DECOMPRESSOR))
+#define YELP_IS_MAGIC_DECOMPRESSOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), YELP_TYPE_MAGIC_DECOMPRESSOR))
+#define YELP_MAGIC_DECOMPRESSOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), YELP_TYPE_MAGIC_DECOMPRESSOR, YelpMagicDecompressorClass))
+
+typedef struct _YelpMagicDecompressor YelpMagicDecompressor;
+typedef struct _YelpMagicDecompressorClass YelpMagicDecompressorClass;
+
+struct _YelpMagicDecompressorClass
+{
+ GObjectClass parent_class;
+};
+
+GType yelp_magic_decompressor_get_type (void);
+
+YelpMagicDecompressor *yelp_magic_decompressor_new (void);
+
+G_END_DECLS
+
+#endif /* __YELP_MAGIC_DECOMPRESSOR_H__ */