[glib] Add GCharsetConverter
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [glib] Add GCharsetConverter
- Date: Mon, 23 Nov 2009 15:30:54 +0000 (UTC)
commit 4b8382823e0f03b59d07473f708f1892dcd743dc
Author: Alexander Larsson <alexl redhat com>
Date: Wed Oct 21 21:25:36 2009 +0200
Add GCharsetConverter
gio/Makefile.am | 2 +
gio/gcharsetconverter.c | 373 +++++++++++++++++++++++++++++++++++++++++++++++
gio/gcharsetconverter.h | 52 +++++++
gio/gio.h | 1 +
gio/giotypes.h | 1 +
5 files changed, 429 insertions(+), 0 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index d0b6935..446b2a4 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -187,6 +187,7 @@ libgio_2_0_la_SOURCES = \
gcancellable.c \
gcontenttype.c \
gcontenttypeprivate.h \
+ gcharsetconverter.c \
gconverter.c \
gdatainputstream.c \
gdataoutputstream.c \
@@ -325,6 +326,7 @@ gio_headers = \
gbufferedoutputstream.h \
gcancellable.h \
gcontenttype.h \
+ gcharsetconverter.h \
gconverter.h \
gdatainputstream.h \
gdataoutputstream.h \
diff --git a/gio/gcharsetconverter.c b/gio/gcharsetconverter.c
new file mode 100644
index 0000000..c2f2c7d
--- /dev/null
+++ b/gio/gcharsetconverter.c
@@ -0,0 +1,373 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * 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: Alexander Larsson <alexl redhat com>
+ */
+
+#include "config.h"
+
+#include <errno.h>
+
+#include "gcontenttypeprivate.h"
+#include "gcharsetconverter.h"
+#include "glib.h"
+#include "ginitable.h"
+#include "gioerror.h"
+#include "glibintl.h"
+
+#include "gioalias.h"
+
+enum {
+ PROP_0,
+ PROP_FROM_CHARSET,
+ PROP_TO_CHARSET
+};
+
+/**
+ * SECTION:gcharsetconverter
+ * @short_description: Convert between charsets
+ * @include: gio/gio.h
+ *
+ * #GCharsetConverter is an implementation of #GConverter based on
+ * GIConv.
+ */
+
+static void g_charset_converter_iface_init (GConverterIface *iface);
+static void g_charset_converter_initable_iface_init (GInitableIface *iface);
+
+/**
+ * GCharsetConverter:
+ *
+ * Conversions between character sets.
+ */
+struct _GCharsetConverter
+{
+ GObject parent_instance;
+
+ char *from;
+ char *to;
+ GIConv iconv;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GCharsetConverter, g_charset_converter, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
+ g_charset_converter_iface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ g_charset_converter_initable_iface_init))
+
+static void
+g_charset_converter_finalize (GObject *object)
+{
+ GCharsetConverter *conv;
+
+ conv = G_CHARSET_CONVERTER (object);
+
+ g_free (conv->from);
+ g_free (conv->to);
+ if (conv->iconv)
+ g_iconv_close (conv->iconv);
+
+ G_OBJECT_CLASS (g_charset_converter_parent_class)->finalize (object);
+}
+
+static void
+g_charset_converter_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GCharsetConverter *conv;
+
+ conv = G_CHARSET_CONVERTER (object);
+
+ switch (prop_id)
+ {
+ case PROP_TO_CHARSET:
+ g_free (conv->to);
+ conv->to = g_value_dup_string (value);
+ break;
+
+ case PROP_FROM_CHARSET:
+ g_free (conv->from);
+ conv->from = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+}
+
+static void
+g_charset_converter_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GCharsetConverter *conv;
+
+ conv = G_CHARSET_CONVERTER (object);
+
+ switch (prop_id)
+ {
+ case PROP_TO_CHARSET:
+ g_value_set_string (value, conv->to);
+ break;
+
+ case PROP_FROM_CHARSET:
+ g_value_set_string (value, conv->from);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+g_charset_converter_class_init (GCharsetConverterClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = g_charset_converter_finalize;
+ gobject_class->get_property = g_charset_converter_get_property;
+ gobject_class->set_property = g_charset_converter_set_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_TO_CHARSET,
+ g_param_spec_string ("to-charset",
+ P_("To Charset"),
+ P_("The character encoding to convert to"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class,
+ PROP_FROM_CHARSET,
+ g_param_spec_string ("from-charset",
+ P_("From Charset"),
+ P_("The character encoding to convert from"),
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+}
+
+static void
+g_charset_converter_init (GCharsetConverter *local)
+{
+}
+
+
+/**
+ * g_charset_converter_new:
+ * @to_charset: destination charset
+ * @from_charset: source charset
+ * @error: #GError for error reporting, or %NULL to ignore.
+ *
+ * Creates a new #GCharsetConverter.
+ *
+ * Returns: a new #GCharsetConverter or %NULL on error.
+ *
+ * Since: 2.24
+ **/
+GCharsetConverter *
+g_charset_converter_new (const gchar *to_charset,
+ const gchar *from_charset,
+ GError **error)
+{
+ GCharsetConverter *conv;
+
+ conv = g_initable_new (G_TYPE_CHARSET_CONVERTER,
+ NULL, error,
+ "to-charset", to_charset,
+ "from-charset", from_charset,
+ NULL);
+
+ return conv;
+}
+
+static void
+g_charset_converter_reset (GConverter *converter)
+{
+ GCharsetConverter *conv = G_CHARSET_CONVERTER (converter);
+
+ if (conv->iconv == NULL)
+ {
+ g_warning ("Invalid object, not initialized");
+ return;
+ }
+
+ g_iconv (conv->iconv, NULL, NULL, NULL, NULL);
+}
+
+static GConverterResult
+g_charset_converter_convert (GConverter *converter,
+ const void *inbuf,
+ gsize inbuf_size,
+ void *outbuf,
+ gsize outbuf_size,
+ GConverterFlags flags,
+ gsize *bytes_read,
+ gsize *bytes_written,
+ GError **error)
+{
+ GCharsetConverter *conv;
+ gsize res;
+ GConverterResult ret;
+ gchar *inbufp, *outbufp;
+ gsize in_left, out_left;
+ int errsv;
+
+ conv = G_CHARSET_CONVERTER (converter);
+
+ if (conv->iconv == NULL)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED,
+ _("Invalid object, not initialized"));
+ return G_CONVERTER_ERROR;
+ }
+
+ /* Iconv never produces output with no input, so handle this
+ specially */
+ if (inbuf_size == 0)
+ {
+ if (flags & G_CONVERTER_INPUT_AT_END)
+ return G_CONVERTER_FINISHED;
+
+ if (flags & G_CONVERTER_FLUSH)
+ return G_CONVERTER_FLUSHED;
+
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT,
+ _("Incomplete multibyte sequence in input"));
+ return G_CONVERTER_ERROR;
+ }
+
+ inbufp = (char *)inbuf;
+ outbufp = (char *)outbuf;
+ in_left = inbuf_size;
+ out_left = outbuf_size;
+
+ res = g_iconv (conv->iconv,
+ &inbufp, &in_left,
+ &outbufp, &out_left);
+
+ *bytes_read = inbufp - (char *)inbuf;
+ *bytes_written = outbufp - (char *)outbuf;
+
+ /* Don't report error if we converted anything */
+ if (res == (gsize) -1 && *bytes_read == 0)
+ {
+ errsv = errno;
+
+ switch (errsv)
+ {
+ case EINVAL:
+ /* Incomplete input text */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT,
+ _("Incomplete multibyte sequence in input"));
+ break;
+
+ case E2BIG:
+ /* Not enough destination space */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+ _("Not enough space in destination"));
+ break;
+
+ case EILSEQ:
+ /* Invalid code sequence */
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+ _("Invalid byte sequence in conversion input"));
+ break;
+
+ default:
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Error during conversion: %s"),
+ g_strerror (errsv));
+ break;
+ }
+ ret = G_CONVERTER_ERROR;
+ }
+ else
+ {
+ ret = G_CONVERTER_CONVERTED;
+
+ if (in_left == 0 &&
+ (flags & G_CONVERTER_INPUT_AT_END))
+ ret = G_CONVERTER_FINISHED;
+ else if (in_left == 0 &&
+ (flags & G_CONVERTER_FLUSH))
+ ret = G_CONVERTER_FLUSHED;
+ }
+
+ return ret;
+}
+
+static void
+g_charset_converter_iface_init (GConverterIface *iface)
+{
+ iface->convert = g_charset_converter_convert;
+ iface->reset = g_charset_converter_reset;
+}
+
+static gboolean
+g_charset_converter_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GCharsetConverter *conv;
+
+ g_return_val_if_fail (G_IS_CHARSET_CONVERTER (initable), FALSE);
+
+ conv = G_CHARSET_CONVERTER (initable);
+
+ if (cancellable != NULL)
+ {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Cancellable initialization not supported"));
+ return FALSE;
+ }
+
+ conv->iconv =
+ g_iconv_open (conv->to, conv->from);
+
+ if (conv->iconv == NULL)
+ {
+ if (errno == EINVAL)
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Conversion from character set '%s' to '%s' is not supported"),
+ conv->from, conv->to);
+ else
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Could not open converter from '%s' to '%s'"),
+ conv->from, conv->to);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+g_charset_converter_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = g_charset_converter_initable_init;
+}
+
+#define __G_CHARSET_CONVERTER_C__
+#include "gioaliasdef.c"
diff --git a/gio/gcharsetconverter.h b/gio/gcharsetconverter.h
new file mode 100644
index 0000000..848eb45
--- /dev/null
+++ b/gio/gcharsetconverter.h
@@ -0,0 +1,52 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * 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: Alexander Larsson <alexl redhat com>
+ */
+
+#ifndef __G_CHARSET_CONVERTER_H__
+#define __G_CHARSET_CONVERTER_H__
+
+#include <gio/gconverter.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_CHARSET_CONVERTER (g_charset_converter_get_type ())
+#define G_CHARSET_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_CHARSET_CONVERTER, GCharsetConverter))
+#define G_CHARSET_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_CHARSET_CONVERTER, GCharsetConverterClass))
+#define G_IS_CHARSET_CONVERTER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_CHARSET_CONVERTER))
+#define G_IS_CHARSET_CONVERTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_CHARSET_CONVERTER))
+#define G_CHARSET_CONVERTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_CHARSET_CONVERTER, GCharsetConverterClass))
+
+typedef struct _GCharsetConverterClass GCharsetConverterClass;
+
+struct _GCharsetConverterClass
+{
+ GObjectClass parent_class;
+};
+
+GType g_charset_converter_get_type (void) G_GNUC_CONST;
+
+GCharsetConverter *g_charset_converter_new (const gchar *to_charset,
+ const gchar *from_charset,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_CHARSET_CONVERTER_H__ */
diff --git a/gio/gio.h b/gio/gio.h
index d2e168e..74cded9 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -35,6 +35,7 @@
#include <gio/gcancellable.h>
#include <gio/gcontenttype.h>
#include <gio/gconverter.h>
+#include <gio/gcharsetconverter.h>
#include <gio/gdatainputstream.h>
#include <gio/gdataoutputstream.h>
#include <gio/gdrive.h>
diff --git a/gio/giotypes.h b/gio/giotypes.h
index adb6341..5592252 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -38,6 +38,7 @@ typedef struct _GAsyncInitable GAsyncInitable;
typedef struct _GBufferedInputStream GBufferedInputStream;
typedef struct _GBufferedOutputStream GBufferedOutputStream;
typedef struct _GCancellable GCancellable;
+typedef struct _GCharsetConverter GCharsetConverter;
typedef struct _GConverter GConverter;
typedef struct _GDataInputStream GDataInputStream;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]