diff options
author | Andy Wingo <wingo@pobox.com> | 2012-02-09 23:14:11 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2012-02-10 13:42:15 +0100 |
commit | e3d4597469a543d97c4997b128509c2ceb13ca2b (patch) | |
tree | d0064b165c9ff0ff1667b54430eaf80a80b1d53d /libguile/strings.c | |
parent | e7cf0457d7c71acd2c597d1644328960f136e4bc (diff) | |
download | guile-e3d4597469a543d97c4997b128509c2ceb13ca2b.tar.gz |
more efficient scm_to_utf8_stringn, scm_to_utf32_stringn
* libguile/strings.c (scm_to_utf8_stringn): More efficient
implementation than calling scm_to_stringn.
(scm_to_utf32_stringn): Likewise.
Diffstat (limited to 'libguile/strings.c')
-rw-r--r-- | libguile/strings.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/libguile/strings.c b/libguile/strings.c index 69632d697..71eee6c48 100644 --- a/libguile/strings.c +++ b/libguile/strings.c @@ -1844,10 +1844,47 @@ scm_to_utf8_string (SCM str) return scm_to_utf8_stringn (str, NULL); } +static size_t +latin1_u8_strlen (const scm_t_uint8 *str, size_t len) +{ + size_t ret, i; + for (i = 0, ret = 0; i < len; i++) + ret += (str[i] < 128) ? 1 : 2; + return ret; +} + +static scm_t_uint8* +latin1_to_u8 (const scm_t_uint8 *str, size_t latin_len, + scm_t_uint8 *u8_result, size_t *u8_lenp) +{ + size_t i, n; + size_t u8_len = latin1_u8_strlen (str, latin_len); + + if (!(u8_result && u8_lenp && *u8_lenp > u8_len)) + u8_result = scm_malloc (u8_len + 1); + if (u8_lenp) + *u8_lenp = u8_len; + + for (i = 0, n = 0; i < latin_len; i++) + n += u8_uctomb (u8_result + n, str[i], u8_len - n); + if (n != u8_len) + abort (); + u8_result[n] = 0; + + return u8_result; +} + char * scm_to_utf8_stringn (SCM str, size_t *lenp) { - return scm_to_stringn (str, lenp, "UTF-8", SCM_FAILED_CONVERSION_ERROR); + if (scm_i_is_narrow_string (str)) + return (char *) latin1_to_u8 ((scm_t_uint8 *) scm_i_string_chars (str), + scm_i_string_length (str), + NULL, lenp); + else + return (char *) u32_to_u8 ((scm_t_uint32*)scm_i_string_wide_chars (str), + scm_i_string_length (str), + NULL, lenp); } scm_t_wchar * @@ -1865,9 +1902,20 @@ scm_to_utf32_stringn (SCM str, size_t *lenp) SCM_VALIDATE_STRING (1, str); if (scm_i_is_narrow_string (str)) - result = (scm_t_wchar *) - scm_to_stringn (str, lenp, "UTF-32", - SCM_FAILED_CONVERSION_ERROR); + { + scm_t_uint8 *codepoints; + size_t i, len; + + codepoints = (scm_t_uint8*) scm_i_string_chars (str); + len = scm_i_string_length (str); + if (lenp) + *lenp = len; + + result = scm_malloc ((len + 1) * sizeof (scm_t_wchar)); + for (i = 0; i < len; i++) + result[i] = codepoints[i]; + result[len] = 0; + } else { size_t len; |