622 lines
19 KiB
Diff
622 lines
19 KiB
Diff
From d3671f2929323eb593c526aa0a69854d92a7a649 Mon Sep 17 00:00:00 2001
|
|
From: Bastien Nocera <hadess@hadess.net>
|
|
Date: Fri, 27 Nov 2009 14:41:11 +0000
|
|
Subject: [PATCH] Add support for BZ2 compression using GIO
|
|
|
|
---
|
|
Makefile.am | 12 +++-
|
|
configure.ac | 8 ++-
|
|
io-xcf.c | 228 ++++++++++++++++++++++++++++-------------------
|
|
yelp-bz2-decompressor.c | 173 +++++++++++++++++++++++++++++++++++
|
|
yelp-bz2-decompressor.h | 53 +++++++++++
|
|
5 files changed, 381 insertions(+), 93 deletions(-)
|
|
create mode 100644 yelp-bz2-decompressor.c
|
|
create mode 100644 yelp-bz2-decompressor.h
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index 29e1de2..f53b98b 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -10,9 +10,19 @@ INCLUDES = \
|
|
|
|
AM_CFLAGS = -g
|
|
|
|
-libioxcf_la_SOURCES = io-xcf.c
|
|
+BZ2_DECOMPRESSOR_FILES = yelp-bz2-decompressor.c yelp-bz2-decompressor.h
|
|
+
|
|
+if GIO_2_23
|
|
+BZ2_DECOMPRESSOR = $(BZ2_DECOMPRESSOR_FILES)
|
|
+else
|
|
+BZ2_DECOMPRESSOR =
|
|
+endif
|
|
+
|
|
+libioxcf_la_SOURCES = io-xcf.c $(BZ2_DECOMPRESSOR)
|
|
libioxcf_la_LDFLAGS = -export_dynamic -avoid-version -module -no-undefined
|
|
libioxcf_la_LIBADD = \
|
|
$(GDKPIXBUF_LIBS) \
|
|
$(GLIB_LIBS) \
|
|
$(GIO_LIBS)
|
|
+
|
|
+EXTRA_DIST = $(BZ2_DECOMPRESSOR_FILES)
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 7b0c4aa..25269cb 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -1,5 +1,6 @@
|
|
AC_INIT(io-xcf, 0.0.1, stephane@delcroix.org)
|
|
AC_CONFIG_SRCDIR(.)
|
|
+AC_CONFIG_HEADERS([config.h])
|
|
|
|
AM_INIT_AUTOMAKE
|
|
|
|
@@ -10,7 +11,12 @@ AC_PROG_LIBTOOL
|
|
PKG_CHECK_MODULES(GLIB, glib-2.0)
|
|
PKG_CHECK_MODULES(GMODULE, gmodule-2.0)
|
|
PKG_CHECK_MODULES(GDKPIXBUF, gdk-pixbuf-2.0)
|
|
-PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.23 gio-unix-2.0, AC_DEFINE(GIO_2_23),old_gio=1)
|
|
+PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.23 gio-unix-2.0, old_gio=0, old_gio=1)
|
|
+
|
|
+if test "x$old_gio" = "x0"; then
|
|
+ AC_DEFINE(GIO_2_23, 1, [Define if GIO is newer than 2.23])
|
|
+fi
|
|
+AM_CONDITIONAL([GIO_2_23],[test "x$old_gio" != "x1"])
|
|
|
|
AC_CHECK_HEADER(bzlib.h,,AC_MSG_ERROR(Can not find bzlib header))
|
|
AC_CHECK_LIB(bz2,BZ2_bzDecompressInit,,AC_MSG_ERROR(Can not find libbz2))
|
|
diff --git a/io-xcf.c b/io-xcf.c
|
|
index e47e525..cb480e9 100644
|
|
--- a/io-xcf.c
|
|
+++ b/io-xcf.c
|
|
@@ -36,13 +36,13 @@
|
|
|
|
#define GDK_PIXBUF_ENABLE_BACKEND
|
|
|
|
+#include "config.h"
|
|
+
|
|
#include <gmodule.h>
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
#include <gio/gio.h>
|
|
#if GIO_2_23
|
|
-#include <gio/gzlibcompressor.h>
|
|
-#include <gio/gunixinputstream.h>
|
|
-#include <gio/gunixoutputstream.h>
|
|
+#include "yelp-bz2-decompressor.h"
|
|
#endif
|
|
#include <math.h>
|
|
#include <string.h>
|
|
@@ -105,13 +105,13 @@
|
|
#define LAYERMODE_GRAINEXTRACT 20
|
|
#define LAYERMODE_GRAINMERGE 21
|
|
|
|
-#define FILETYPE_STREAMCLOSED -1
|
|
-#define FILETYPE_UNKNOWN 0
|
|
-#define FILETYPE_XCF 1
|
|
-#define FILETYPE_XCF_BZ2 2
|
|
-#if GIO_2_23
|
|
-#define FILETYPE_XCF_GZ 3
|
|
-#endif
|
|
+enum {
|
|
+ FILETYPE_STREAMCLOSED = -1,
|
|
+ FILETYPE_UNKNOWN = 0,
|
|
+ FILETYPE_XCF,
|
|
+ FILETYPE_XCF_BZ2,
|
|
+ FILETYPE_XCF_GZ
|
|
+};
|
|
|
|
typedef struct _XcfContext XcfContext;
|
|
struct _XcfContext {
|
|
@@ -1198,10 +1198,80 @@ xcf_image_load_real (FILE *f, XcfContext *context, GError **error)
|
|
static GdkPixbuf*
|
|
xcf_image_load (FILE *f, GError **error)
|
|
{
|
|
- guchar buffer[4];
|
|
- fread (buffer, sizeof(guchar), 4, f);
|
|
+ guint type;
|
|
+
|
|
+ guchar buffer[8];
|
|
+ fread (buffer, sizeof(guchar), 8, f);
|
|
rewind (f);
|
|
- if (!strncmp (buffer, "BZh", 3)) { //Decompress the xcf.bz2 file to a temp file
|
|
+
|
|
+ if (!strncmp (buffer, "BZh", 3)) {
|
|
+ type = FILETYPE_XCF_BZ2;
|
|
+ } else if (!strncmp (buffer, "\x1f\x8b", 2)) {
|
|
+ type = FILETYPE_XCF_GZ;
|
|
+ } else if (!strncmp (buffer, "gimp xcf", 8)) {
|
|
+ type = FILETYPE_XCF;
|
|
+ } else {
|
|
+ g_set_error (error,
|
|
+ GDK_PIXBUF_ERROR,
|
|
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
|
|
+ "Unknown XCF file type");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (type == FILETYPE_XCF)
|
|
+ return xcf_image_load_real (f, NULL, error);
|
|
+
|
|
+#if GIO_2_23
|
|
+ if (type == FILETYPE_XCF_BZ2 ||
|
|
+ type == FILETYPE_XCF_GZ) {
|
|
+ GConverter *decompressor;
|
|
+ GInputStream *input, *stream;
|
|
+
|
|
+ if (type == FILETYPE_XCF_BZ2)
|
|
+ decompressor = G_CONVERTER (yelp_bz2_decompressor_new ());
|
|
+ else
|
|
+ decompressor = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
|
|
+ input = g_unix_input_stream_new (fileno (f), FALSE);
|
|
+ stream = (GInputStream *) g_converter_input_stream_new (input, decompressor);
|
|
+ g_object_unref (decompressor);
|
|
+ g_object_unref (input);
|
|
+
|
|
+ gchar *tempname;
|
|
+ gint fd = g_file_open_tmp ("gdkpixbuf-xcf-tmp.XXXXXX", &tempname, NULL);
|
|
+ if (fd < 0) {
|
|
+ gint save_errno = errno;
|
|
+ g_set_error (error,
|
|
+ G_FILE_ERROR,
|
|
+ g_file_error_from_errno (save_errno),
|
|
+ "Failed to create temporary file when loading Xcf image");
|
|
+ return NULL;
|
|
+ }
|
|
+ GOutputStream *output;
|
|
+ output = g_unix_output_stream_new (fd, TRUE);
|
|
+ if (!g_output_stream_splice (G_OUTPUT_STREAM (output), stream,
|
|
+ G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
|
+ NULL, NULL)) {
|
|
+ LOG ("splicing failed\n");
|
|
+ g_set_error (error,
|
|
+ GDK_PIXBUF_ERROR,
|
|
+ GDK_PIXBUF_ERROR_FAILED,
|
|
+ "Decompression error while loading Xcf.gz file");
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ FILE *file;
|
|
+ file = fopen (tempname, "r");
|
|
+ g_unlink (tempname);
|
|
+ g_free (tempname);
|
|
+
|
|
+ GdkPixbuf *pixbuf = xcf_image_load_real (file, NULL, error);
|
|
+ fclose (file);
|
|
+
|
|
+ return pixbuf;
|
|
+ }
|
|
+#else
|
|
+ /* Decompress the xcf.bz2 file to a temp file */
|
|
+ if (type == FILETYPE_XCF_BZ2) {
|
|
gchar *tempname;
|
|
gint fd = g_file_open_tmp ("gdkpixbuf-xcf-tmp.XXXXXX", &tempname, NULL);
|
|
if (fd < 0) {
|
|
@@ -1282,52 +1352,13 @@ xcf_image_load (FILE *f, GError **error)
|
|
GdkPixbuf *pixbuf = xcf_image_load_real (file, NULL, error);
|
|
fclose (file);
|
|
return pixbuf;
|
|
-#if GIO_2_23
|
|
- } else if (!strncmp (buffer, "\x1f\x8b", 2)) { //Decompress the .gz to a temp file
|
|
- GZlibDecompressor *compressor;
|
|
- GInputStream *input, *stream;
|
|
-
|
|
- compressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
|
|
- input = g_unix_input_stream_new (fileno (f), FALSE);
|
|
- stream = (GInputStream *) g_converter_input_stream_new (input, (GConverter *) (compressor));
|
|
- g_object_unref (compressor);
|
|
- g_object_unref (input);
|
|
-
|
|
- gchar *tempname;
|
|
- gint fd = g_file_open_tmp ("gdkpixbuf-xcf-tmp.XXXXXX", &tempname, NULL);
|
|
- if (fd < 0) {
|
|
- gint save_errno = errno;
|
|
- g_set_error (error,
|
|
- G_FILE_ERROR,
|
|
- g_file_error_from_errno (save_errno),
|
|
- "Failed to create temporary file when loading Xcf image");
|
|
- return NULL;
|
|
- }
|
|
- GOutputStream *output;
|
|
- output = g_unix_output_stream_new (fd, TRUE);
|
|
- if (!g_output_stream_splice (G_OUTPUT_STREAM (output), stream,
|
|
- G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
|
- NULL, NULL)) {
|
|
- LOG ("splicing failed\n");
|
|
- g_set_error (error,
|
|
- GDK_PIXBUF_ERROR,
|
|
- GDK_PIXBUF_ERROR_FAILED,
|
|
- "Decompression error while loading Xcf.gz file");
|
|
- return NULL;
|
|
- }
|
|
-
|
|
- FILE *file;
|
|
- file = fopen (tempname, "r");
|
|
- g_unlink (tempname);
|
|
- g_free (tempname);
|
|
-
|
|
- GdkPixbuf *pixbuf = xcf_image_load_real (file, NULL, error);
|
|
- fclose (file);
|
|
-
|
|
- return pixbuf;
|
|
+ } else {
|
|
+ g_set_error (error,
|
|
+ GDK_PIXBUF_ERROR,
|
|
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
|
|
+ "Unhandled XCF file type");
|
|
+ }
|
|
#endif
|
|
- } else
|
|
- return xcf_image_load_real (f, NULL, error);
|
|
}
|
|
|
|
|
|
@@ -1387,22 +1418,9 @@ xcf_image_stop_load (gpointer data, GError **error)
|
|
|
|
g_return_val_if_fail (data, TRUE);
|
|
|
|
- if (context->type == FILETYPE_XCF ||
|
|
- context->type == FILETYPE_XCF_BZ2) {
|
|
- fflush (context->file);
|
|
- rewind (context->file);
|
|
- if (context->tempname) {
|
|
- g_unlink (context->tempname);
|
|
- g_free (context->tempname);
|
|
- context->tempname = NULL;
|
|
- }
|
|
- GdkPixbuf *pixbuf = xcf_image_load_real (context->file, context, error);
|
|
- if (!pixbuf)
|
|
- retval = FALSE;
|
|
- else
|
|
- g_object_unref (pixbuf);
|
|
#if GIO_2_23
|
|
- } else if (context->type == FILETYPE_XCF_GZ) {
|
|
+ if (context->type == FILETYPE_XCF_GZ ||
|
|
+ context->type == FILETYPE_XCF_BZ2) {
|
|
g_object_unref (context->input);
|
|
context->input = NULL;
|
|
|
|
@@ -1426,11 +1444,28 @@ xcf_image_stop_load (gpointer data, GError **error)
|
|
retval = FALSE;
|
|
goto bail;
|
|
}
|
|
+ goto done;
|
|
+ }
|
|
#endif
|
|
+ if (context->type == FILETYPE_XCF ||
|
|
+ context->type == FILETYPE_XCF_BZ2) {
|
|
+ fflush (context->file);
|
|
+ rewind (context->file);
|
|
+ if (context->tempname) {
|
|
+ g_unlink (context->tempname);
|
|
+ g_free (context->tempname);
|
|
+ context->tempname = NULL;
|
|
+ }
|
|
+ GdkPixbuf *pixbuf = xcf_image_load_real (context->file, context, error);
|
|
+ if (!pixbuf)
|
|
+ retval = FALSE;
|
|
+ else
|
|
+ g_object_unref (pixbuf);
|
|
} else {
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
+done:
|
|
fflush (context->file);
|
|
rewind (context->file);
|
|
if (context->tempname) {
|
|
@@ -1475,11 +1510,30 @@ xcf_image_load_increment (gpointer data,
|
|
}
|
|
|
|
if (context->type == FILETYPE_UNKNOWN) { // first chunk
|
|
- if (!strncmp (buf, "gimp xcf ", 9))
|
|
+ if (!strncmp (buf, "gimp xcf ", 9)) {
|
|
context->type = FILETYPE_XCF;
|
|
- else if (!strncmp (buf, "BZh", 3)) {
|
|
+ } else if (!strncmp (buf, "BZh", 3)) {
|
|
context->type = FILETYPE_XCF_BZ2;
|
|
+ } else if (!strncmp (buf, "\x1f\x8b", 2)) {
|
|
+ context->type = FILETYPE_XCF_GZ;
|
|
+ }
|
|
|
|
+#if GIO_2_23
|
|
+ if (context->type == FILETYPE_XCF_GZ ||
|
|
+ context->type == FILETYPE_XCF_BZ2) {
|
|
+ GConverter *decompressor;
|
|
+
|
|
+ if (context->type == FILETYPE_XCF_BZ2)
|
|
+ decompressor = G_CONVERTER (yelp_bz2_decompressor_new ());
|
|
+ else
|
|
+ decompressor = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
|
|
+
|
|
+ context->input = g_memory_input_stream_new ();
|
|
+ context->stream = (GInputStream *) g_converter_input_stream_new (context->input, decompressor);
|
|
+ g_object_unref (decompressor);
|
|
+ }
|
|
+#else
|
|
+ if (context->type == FILETYPE_XCF_BZ2) {
|
|
//Initialize bzlib
|
|
context->bz_stream = g_new (bz_stream, 1);
|
|
context->bz_stream->bzalloc = NULL;
|
|
@@ -1493,23 +1547,20 @@ xcf_image_load_increment (gpointer data,
|
|
context->bz_stream = NULL;
|
|
return FALSE;
|
|
}
|
|
-#if GIO_2_23
|
|
- } else if (!strncmp (buf, "\x1f\x8b", 2)) {
|
|
- GZlibDecompressor *compressor;
|
|
-
|
|
- context->type = FILETYPE_XCF_GZ;
|
|
- compressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP);
|
|
-
|
|
- context->input = g_memory_input_stream_new ();
|
|
- context->stream = (GInputStream *) g_converter_input_stream_new (context->input, (GConverter *) (compressor));
|
|
- g_object_unref (compressor);
|
|
-#endif
|
|
}
|
|
+#endif
|
|
LOG ("File type %d\n", context->type);
|
|
}
|
|
|
|
gchar *outbuf;
|
|
switch (context->type) {
|
|
+#if GIO_2_23
|
|
+ case FILETYPE_XCF_GZ:
|
|
+ case FILETYPE_XCF_BZ2:
|
|
+ g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (context->input),
|
|
+ buf, size, NULL);
|
|
+ break;
|
|
+#else
|
|
case FILETYPE_XCF_BZ2:
|
|
outbuf = g_new (gchar, 65536);
|
|
context->bz_stream->next_in = (gchar*)buf;
|
|
@@ -1563,11 +1614,6 @@ xcf_image_load_increment (gpointer data,
|
|
context->bz_stream = NULL;
|
|
}
|
|
break;
|
|
-#if GIO_2_23
|
|
- case FILETYPE_XCF_GZ:
|
|
- g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (context->input),
|
|
- buf, size, NULL);
|
|
- break;
|
|
#endif
|
|
case FILETYPE_XCF:
|
|
default:
|
|
diff --git a/yelp-bz2-decompressor.c b/yelp-bz2-decompressor.c
|
|
new file mode 100644
|
|
index 0000000..98802ce
|
|
--- /dev/null
|
|
+++ b/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/yelp-bz2-decompressor.h b/yelp-bz2-decompressor.h
|
|
new file mode 100644
|
|
index 0000000..e067f26
|
|
--- /dev/null
|
|
+++ b/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__ */
|
|
--
|
|
1.6.6.1
|
|
|