g_convert and g_utf8_validate
- From: Havoc Pennington <hp redhat com>
- To: gtk-devel-list gnome org
- Subject: g_convert and g_utf8_validate
- Date: 10 Jul 2000 20:35:31 -0400
Hi,
Two thingies for glib. g_utf8_validate() is supposed to be robust
against a random stream of bytes, so check it over and find my broken
assumptions.
Havoc
gboolean
g_utf8_validate (const gchar *str,
gint max_len,
const gchar **end)
{
const gchar *p;
gboolean retval = TRUE;
if (end)
*end = str;
p = str;
while ((max_len < 0 || (p - str) < max_len) && *p)
{
int i, mask = 0, len;
gunichar result;
unsigned char c = (unsigned char) *p;
UTF8_COMPUTE (c, mask, len);
if (len == -1)
{
retval = FALSE;
break;
}
/* check that the expected number of bytes exists in str */
if (max_len >= 0 &&
((max_len - (p - str)) < len))
{
retval = FALSE;
break;
}
UTF8_GET (result, p, i, mask, len);
if (result == (gunichar)-1)
{
retval = FALSE;
break;
}
p += len;
if (end)
*end = p;
}
return retval;
}
/* iconv_open() etc. are not thread safe */
G_LOCK_DEFINE_STATIC (iconv_lock);
gchar*
g_convert (const gchar *str,
gint len,
const gchar *to_codeset,
const gchar *from_codeset,
gint *bytes_converted)
{
gchar *dest;
gchar *outp;
const gchar *p;
size_t inbytes_remaining;
size_t outbytes_remaining;
size_t err;
iconv_t cd;
size_t outbuf_size;
g_return_val_if_fail (str != NULL, NULL);
g_return_val_if_fail (to_codeset != NULL, NULL);
g_return_val_if_fail (from_codeset != NULL, NULL);
G_LOCK (iconv_lock);
cd = iconv_open (to_codeset, from_codeset);
if (cd == (iconv_t) -1)
{
/* Something went wrong. */
if (errno == EINVAL)
; /* don't warn; just return NULL with bytes_converted of 0 */
else
g_warning ("Failed to convert character set `%s' to `%s': %s",
from_codeset, to_codeset, strerror (errno));
if (bytes_converted)
*bytes_converted = 0;
G_UNLOCK (iconv_lock);
return NULL;
}
if (len < 0)
len = strlen (str);
p = str;
inbytes_remaining = len;
outbuf_size = len + 1; /* + 1 for nul in case len == 1 */
outbytes_remaining = outbuf_size - 1; /* -1 for nul */
outp = dest = g_malloc (outbuf_size);
again:
err = iconv (cd, &p, &inbytes_remaining, &outp, &outbytes_remaining);
if (err == (size_t) -1)
{
if (errno == E2BIG)
{
size_t used = outp - dest;
outbuf_size *= 2;
dest = g_realloc (dest, outbuf_size);
outp = dest + used;
outbytes_remaining = outbuf_size - used - 1; /* -1 for nul */
goto again;
}
else
g_warning ("iconv() failed: %s", strerror (errno));
}
*outp = '\0';
if (iconv_close (cd) != 0)
g_warning ("Failed to close iconv() conversion descriptor: %s",
strerror (errno));
if (bytes_converted)
*bytes_converted = p - str;
G_UNLOCK (iconv_lock);
if (p == str)
{
g_free (dest);
return NULL;
}
else
return dest;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]