From 46bc8ca1541d80b272e2ef0cbb499a4cb1bea659 Mon Sep 17 00:00:00 2001 From: John Mark Bell Date: Mon, 11 Jul 2005 18:10:10 +0000 Subject: [PATCH] [project @ 2005-07-11 18:10:10 by jmb] Cache previous iconv conversion descriptor svn path=/import/netsurf/; revision=1792 --- desktop/netsurf.c | 3 +++ utils/utf8.c | 56 +++++++++++++++++++++++++++++++++++++---------- utils/utf8.h | 2 ++ 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/desktop/netsurf.c b/desktop/netsurf.c index d0c2080ec..606774bf3 100644 --- a/desktop/netsurf.c +++ b/desktop/netsurf.c @@ -23,6 +23,7 @@ #endif #include "netsurf/utils/log.h" #include "netsurf/utils/url.h" +#include "netsurf/utils/utf8.h" #include "netsurf/utils/utils.h" bool netsurf_quit = false; @@ -73,6 +74,7 @@ void netsurf_init(int argc, char** argv) "machine <%s>", utsname.sysname, utsname.nodename, utsname.release, utsname.version, utsname.machine)); + lib_init(); url_init(); gui_init(argc, argv); @@ -103,6 +105,7 @@ void netsurf_exit(void) gui_quit(); content_quit(); fetch_quit(); + utf8_finalise(); } diff --git a/utils/utf8.c b/utils/utf8.c index 801fca1a3..6c06c76f5 100644 --- a/utils/utf8.c +++ b/utils/utf8.c @@ -198,6 +198,26 @@ size_t utf8_next(const char *s, size_t l, size_t o) return o; } +/* Cache of previous iconv conversion descriptor used by utf8_convert */ +static struct { + char from[32]; /**< Encoding name to convert from */ + char to[32]; /**< Encoding name to convert to */ + iconv_t cd; /**< Iconv conversion descriptor */ +} last_cd; + +/** + * Finalise the UTF-8 library + */ +void utf8_finalise(void) +{ + if (last_cd.cd != 0) + iconv_close(last_cd.cd); + + /* paranoia follows */ + last_cd.from[0] = '\0'; + last_cd.to[0] = '\0'; + last_cd.cd = 0; +} /** * Convert a UTF8 string into the named encoding @@ -262,12 +282,29 @@ utf8_convert_ret utf8_convert(const char *string, size_t len, in = (char *)string; - cd = iconv_open(to, from); - if (cd == (iconv_t)-1) { - if (errno == EINVAL) - return UTF8_CONVERT_BADENC; - /* default to no memory */ - return UTF8_CONVERT_NOMEM; + /* we cache the last used conversion descriptor, + * so check if we're trying to use it here */ + if (strncasecmp(last_cd.from, from, 32) == 0 && + strncasecmp(last_cd.to, to, 32) == 0) { + cd = last_cd.cd; + } + else { + /* no match, so create a new cd */ + cd = iconv_open(to, from); + if (cd == (iconv_t)-1) { + if (errno == EINVAL) + return UTF8_CONVERT_BADENC; + /* default to no memory */ + return UTF8_CONVERT_NOMEM; + } + + /* close the last cd - we don't care if this fails */ + iconv_close(last_cd.cd); + + /* and copy the to/from/cd data into last_cd */ + strncpy(last_cd.from, from, 32); + strncpy(last_cd.to, to, 32); + last_cd.cd = cd; } slen = len ? len : strlen(string); @@ -278,15 +315,12 @@ utf8_convert_ret utf8_convert(const char *string, size_t len, rlen = slen * 4 + 4; temp = out = malloc(rlen); - if (!out) { - iconv_close(cd); + if (!out) return UTF8_CONVERT_NOMEM; - } /* perform conversion */ if (iconv(cd, &in, &slen, &out, &rlen) == (size_t)-1) { free(temp); - iconv_close(cd); /** \todo handle the various cases properly * There are 3 possible error cases: * a) Insufficiently large output buffer @@ -295,8 +329,6 @@ utf8_convert_ret utf8_convert(const char *string, size_t len, return UTF8_CONVERT_NOMEM; } - iconv_close(cd); - *(result) = realloc(temp, out - temp + 4); if (!(*result)) { free(temp); diff --git a/utils/utf8.h b/utils/utf8.h index a1d98685d..a77af29d0 100644 --- a/utils/utf8.h +++ b/utils/utf8.h @@ -31,4 +31,6 @@ utf8_convert_ret utf8_to_enc(const char *string, const char *encname, utf8_convert_ret utf8_from_enc(const char *string, const char *encname, size_t len, char **result); +void utf8_finalise(void); + #endif