[glib] Add fallback mode to GCharsetConverter



commit 134e9bd84f6311e8b18fe69ce8df030561aa12d9
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Nov 23 16:19:08 2009 +0100

    Add fallback mode to GCharsetConverter

 gio/gcharsetconverter.c |   75 ++++++++++++++++++++++++++++++++++++++++++++--
 gio/gcharsetconverter.h |    3 ++
 2 files changed, 74 insertions(+), 4 deletions(-)
---
diff --git a/gio/gcharsetconverter.c b/gio/gcharsetconverter.c
index c2f2c7d..29e1acf 100644
--- a/gio/gcharsetconverter.c
+++ b/gio/gcharsetconverter.c
@@ -36,7 +36,8 @@
 enum {
   PROP_0,
   PROP_FROM_CHARSET,
-  PROP_TO_CHARSET
+  PROP_TO_CHARSET,
+  PROP_USE_FALLBACK
 };
 
 /**
@@ -63,6 +64,8 @@ struct _GCharsetConverter
   char *from;
   char *to;
   GIConv iconv;
+  gboolean use_fallback;
+  guint n_fallback_errors;
 };
 
 G_DEFINE_TYPE_WITH_CODE (GCharsetConverter, g_charset_converter, G_TYPE_OBJECT,
@@ -108,6 +111,10 @@ g_charset_converter_set_property (GObject      *object,
       conv->from = g_value_dup_string (value);
       break;
 
+    case PROP_USE_FALLBACK:
+      conv->use_fallback = g_value_get_boolean (value);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -135,6 +142,10 @@ g_charset_converter_get_property (GObject    *object,
       g_value_set_string (value, conv->from);
       break;
 
+    case PROP_USE_FALLBACK:
+      g_value_set_boolean (value, conv->use_fallback);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -166,7 +177,15 @@ g_charset_converter_class_init (GCharsetConverterClass *klass)
 							NULL,
 							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
 							G_PARAM_STATIC_STRINGS));
-
+  g_object_class_install_property (gobject_class,
+				   PROP_USE_FALLBACK,
+				   g_param_spec_boolean ("use-fallback",
+							 P_("Fallback enabled"),
+							 P_("Use fallback (of form \\<hexval>) for invalid bytes"),
+							 FALSE,
+							 G_PARAM_READWRITE |
+							 G_PARAM_CONSTRUCT |
+							 G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -215,6 +234,7 @@ g_charset_converter_reset (GConverter *converter)
     }
 
   g_iconv (conv->iconv, NULL, NULL, NULL, NULL);
+  conv->n_fallback_errors = 0;
 }
 
 static GConverterResult
@@ -292,8 +312,29 @@ g_charset_converter_convert (GConverter *converter,
 
 	case EILSEQ:
 	  /* Invalid code sequence */
-	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
-			       _("Invalid byte sequence in conversion input"));
+	  if (conv->use_fallback)
+	    {
+	      if (outbuf_size < 3)
+		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
+				     _("Not enough space in destination"));
+	      else
+		{
+		  const char hex[] = "0123456789ABCDEF";
+		  guint8 v = *(guint8 *)inbuf;
+		  guint8 *out = (guint8 *)outbuf;
+		  out[0] = '\\';
+		  out[1] = hex[(v & 0xf0) >> 4];
+		  out[2] = hex[(v & 0x0f) >> 0];
+		  *bytes_read = 1;
+		  *bytes_written = 3;
+		  in_left--;
+		  conv->n_fallback_errors++;
+		  goto ok;
+		}
+	    }
+	  else
+	    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+				 _("Invalid byte sequence in conversion input"));
 	  break;
 
 	default:
@@ -306,6 +347,7 @@ g_charset_converter_convert (GConverter *converter,
     }
   else
     {
+    ok:
       ret = G_CONVERTER_CONVERTED;
 
       if (in_left == 0 &&
@@ -319,6 +361,31 @@ g_charset_converter_convert (GConverter *converter,
   return ret;
 }
 
+void
+g_charset_converter_set_use_fallback (GCharsetConverter *converter,
+				      gboolean use_fallback)
+{
+  use_fallback = !!use_fallback;
+
+  if (converter->use_fallback != use_fallback)
+    {
+      converter->use_fallback = use_fallback;
+      g_object_notify (G_OBJECT (converter), "use-fallback");
+    }
+}
+
+gboolean
+g_charset_converter_get_use_fallback (GCharsetConverter *converter)
+{
+  return converter->use_fallback;
+}
+
+guint
+g_charset_converter_get_num_fallbacks (GCharsetConverter *converter)
+{
+  return converter->n_fallback_errors;
+}
+
 static void
 g_charset_converter_iface_init (GConverterIface *iface)
 {
diff --git a/gio/gcharsetconverter.h b/gio/gcharsetconverter.h
index 848eb45..a173acc 100644
--- a/gio/gcharsetconverter.h
+++ b/gio/gcharsetconverter.h
@@ -46,6 +46,9 @@ 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);
+void               g_charset_converter_set_use_fallback (GCharsetConverter *converter,
+							 gboolean use_fallback);
+gboolean           g_charset_converter_get_use_fallback (GCharsetConverter *converter);
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]