diff options
author | Mark H Weaver <mhw@netris.org> | 2012-04-04 18:58:44 -0400 |
---|---|---|
committer | Mark H Weaver <mhw@netris.org> | 2012-04-04 18:58:44 -0400 |
commit | bbb9f000ad52282ee1a0518b65437baf20c3d17c (patch) | |
tree | 270f1ab225107ae8cb2a58fe5e8259877d6ab5ea | |
parent | 51853eee69ca5811ae0661eb91868121c6ad1d74 (diff) | |
download | guile-bbb9f000ad52282ee1a0518b65437baf20c3d17c.tar.gz |
Fix scm_to_utf8_stringn once and for all; optimize; add tests
* libguile/strings.c (scm_to_utf8_stringn): Fix another new bug in this
recent comedy of errors: pass the size of the preallocated buffer to
u32_to_u8. Arrange to call 'scm_i_string_wide_chars' and
'scm_i_string_length' only once each. Rename local variables for
improved code clarity.
* test-suite/standalone/test-conversion.c (test_to_utf8_stringn): New
function to test scm_to_utf8_stringn.
-rw-r--r-- | libguile/strings.c | 22 | ||||
-rw-r--r-- | test-suite/standalone/test-conversion.c | 69 |
2 files changed, 80 insertions, 11 deletions
diff --git a/libguile/strings.c b/libguile/strings.c index ec55c501b..07356fcaf 100644 --- a/libguile/strings.c +++ b/libguile/strings.c @@ -1929,28 +1929,28 @@ scm_to_utf8_stringn (SCM str, size_t *lenp) NULL, lenp); else { + scm_t_uint32 *chars = (scm_t_uint32 *) scm_i_string_wide_chars (str); scm_t_uint8 *buf, *ret; - size_t predicted_len, actual_len; /* length in bytes */ + size_t num_chars = scm_i_string_length (str); + size_t num_bytes_predicted, num_bytes_actual; - predicted_len = u32_u8_length_in_bytes - ((scm_t_uint32 *) scm_i_string_wide_chars (str), - scm_i_string_length (str)); + num_bytes_predicted = u32_u8_length_in_bytes (chars, num_chars); if (lenp) { - *lenp = predicted_len; - buf = scm_malloc (predicted_len); + *lenp = num_bytes_predicted; + buf = scm_malloc (num_bytes_predicted); } else { - buf = scm_malloc (predicted_len + 1); - buf[predicted_len] = 0; + buf = scm_malloc (num_bytes_predicted + 1); + buf[num_bytes_predicted] = 0; } - ret = u32_to_u8 ((scm_t_uint32 *) scm_i_string_wide_chars (str), - scm_i_string_length (str), buf, &actual_len); + num_bytes_actual = num_bytes_predicted; + ret = u32_to_u8 (chars, num_chars, buf, &num_bytes_actual); - if (SCM_LIKELY (ret == buf && actual_len == predicted_len)) + if (SCM_LIKELY (ret == buf && num_bytes_actual == num_bytes_predicted)) return (char *) ret; /* An error: a bad codepoint. */ diff --git a/test-suite/standalone/test-conversion.c b/test-suite/standalone/test-conversion.c index 09b74bf17..700e5b3d4 100644 --- a/test-suite/standalone/test-conversion.c +++ b/test-suite/standalone/test-conversion.c @@ -1079,6 +1079,74 @@ test_locale_strings () } static void +test_to_utf8_stringn () +{ + scm_t_wchar wstr[] = { 0x20, /* 0x20 */ + 0xDF, /* 0xC3, 0x9F */ + 0x65E5, /* 0xE6, 0x97, 0xA5 */ + 0x1D400 }; /* 0xF0, 0x9D, 0x90, 0x80 */ + + SCM str0 = scm_from_utf32_stringn (wstr, 1); /* ASCII */ + SCM str1 = scm_from_utf32_stringn (wstr, 2); /* Narrow */ + SCM str2 = scm_from_utf32_stringn (wstr, 4); /* Wide */ + + char cstr0[] = { 0x20, 0 }; + char cstr1[] = { 0x20, 0xC3, 0x9F, 0 }; + char cstr2[] = { 0x20, 0xC3, 0x9F, 0xE6, 0x97, 0xA5, + 0xF0, 0x9D, 0x90, 0x80, 0 }; + char *cstr; + size_t len; + + /* Test conversion of ASCII string */ + cstr = scm_to_utf8_stringn (str0, &len); + if (len + 1 != sizeof (cstr0) || memcmp (cstr, cstr0, len)) + { + fprintf (stderr, "fail: scm_to_utf8_stringn (<ASCII>, &len)"); + exit (EXIT_FAILURE); + } + free (cstr); + cstr = scm_to_utf8_stringn (str0, NULL); + if (memcmp (cstr, cstr0, len + 1)) + { + fprintf (stderr, "fail: scm_to_utf8_stringn (<ASCII>, NULL)"); + exit (EXIT_FAILURE); + } + free (cstr); + + /* Test conversion of narrow string */ + cstr = scm_to_utf8_stringn (str1, &len); + if (len + 1 != sizeof (cstr1) || memcmp (cstr, cstr1, len)) + { + fprintf (stderr, "fail: scm_to_utf8_stringn (<NARROW>, &len)"); + exit (EXIT_FAILURE); + } + free (cstr); + cstr = scm_to_utf8_stringn (str1, NULL); + if (memcmp (cstr, cstr1, len + 1)) + { + fprintf (stderr, "fail: scm_to_utf8_stringn (<NARROW>, NULL)"); + exit (EXIT_FAILURE); + } + free (cstr); + + /* Test conversion of wide string */ + cstr = scm_to_utf8_stringn (str2, &len); + if (len + 1 != sizeof (cstr2) || memcmp (cstr, cstr2, len)) + { + fprintf (stderr, "fail: scm_to_utf8_stringn (<WIDE>, &len)"); + exit (EXIT_FAILURE); + } + free (cstr); + cstr = scm_to_utf8_stringn (str2, NULL); + if (memcmp (cstr, cstr2, len + 1)) + { + fprintf (stderr, "fail: scm_to_utf8_stringn (<WIDE>, NULL)"); + exit (EXIT_FAILURE); + } + free (cstr); +} + +static void test_is_exact () { if (1 != scm_is_exact (scm_c_eval_string ("3"))) @@ -1122,6 +1190,7 @@ tests (void *data, int argc, char **argv) test_from_double (); test_to_double (); test_locale_strings (); + test_to_utf8_stringn (); test_is_exact (); test_is_inexact (); } |