Add fallback mode to GCharsetConverter

This commit is contained in:
Alexander Larsson 2009-11-23 16:19:08 +01:00
parent 4b8382823e
commit 134e9bd84f
2 changed files with 74 additions and 4 deletions

View File

@ -36,7 +36,8 @@
enum { enum {
PROP_0, PROP_0,
PROP_FROM_CHARSET, PROP_FROM_CHARSET,
PROP_TO_CHARSET PROP_TO_CHARSET,
PROP_USE_FALLBACK
}; };
/** /**
@ -63,6 +64,8 @@ struct _GCharsetConverter
char *from; char *from;
char *to; char *to;
GIConv iconv; GIConv iconv;
gboolean use_fallback;
guint n_fallback_errors;
}; };
G_DEFINE_TYPE_WITH_CODE (GCharsetConverter, g_charset_converter, G_TYPE_OBJECT, 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); conv->from = g_value_dup_string (value);
break; break;
case PROP_USE_FALLBACK:
conv->use_fallback = g_value_get_boolean (value);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -135,6 +142,10 @@ g_charset_converter_get_property (GObject *object,
g_value_set_string (value, conv->from); g_value_set_string (value, conv->from);
break; break;
case PROP_USE_FALLBACK:
g_value_set_boolean (value, conv->use_fallback);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -166,7 +177,15 @@ g_charset_converter_class_init (GCharsetConverterClass *klass)
NULL, NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS)); 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 static void
@ -215,6 +234,7 @@ g_charset_converter_reset (GConverter *converter)
} }
g_iconv (conv->iconv, NULL, NULL, NULL, NULL); g_iconv (conv->iconv, NULL, NULL, NULL, NULL);
conv->n_fallback_errors = 0;
} }
static GConverterResult static GConverterResult
@ -292,8 +312,29 @@ g_charset_converter_convert (GConverter *converter,
case EILSEQ: case EILSEQ:
/* Invalid code sequence */ /* Invalid code sequence */
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, if (conv->use_fallback)
_("Invalid byte sequence in conversion input")); {
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; break;
default: default:
@ -306,6 +347,7 @@ g_charset_converter_convert (GConverter *converter,
} }
else else
{ {
ok:
ret = G_CONVERTER_CONVERTED; ret = G_CONVERTER_CONVERTED;
if (in_left == 0 && if (in_left == 0 &&
@ -319,6 +361,31 @@ g_charset_converter_convert (GConverter *converter,
return ret; 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 static void
g_charset_converter_iface_init (GConverterIface *iface) g_charset_converter_iface_init (GConverterIface *iface)
{ {

View File

@ -46,6 +46,9 @@ GType g_charset_converter_get_type (void) G_GNUC_CONST;
GCharsetConverter *g_charset_converter_new (const gchar *to_charset, GCharsetConverter *g_charset_converter_new (const gchar *to_charset,
const gchar *from_charset, const gchar *from_charset,
GError **error); 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 G_END_DECLS