mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-14 23:50:19 +02:00
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.
This commit is contained in:
parent
51853eee69
commit
bbb9f000ad
2 changed files with 80 additions and 11 deletions
|
@ -1929,28 +1929,28 @@ scm_to_utf8_stringn (SCM str, size_t *lenp)
|
||||||
NULL, lenp);
|
NULL, lenp);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
scm_t_uint32 *chars = (scm_t_uint32 *) scm_i_string_wide_chars (str);
|
||||||
scm_t_uint8 *buf, *ret;
|
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
|
num_bytes_predicted = u32_u8_length_in_bytes (chars, num_chars);
|
||||||
((scm_t_uint32 *) scm_i_string_wide_chars (str),
|
|
||||||
scm_i_string_length (str));
|
|
||||||
|
|
||||||
if (lenp)
|
if (lenp)
|
||||||
{
|
{
|
||||||
*lenp = predicted_len;
|
*lenp = num_bytes_predicted;
|
||||||
buf = scm_malloc (predicted_len);
|
buf = scm_malloc (num_bytes_predicted);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buf = scm_malloc (predicted_len + 1);
|
buf = scm_malloc (num_bytes_predicted + 1);
|
||||||
buf[predicted_len] = 0;
|
buf[num_bytes_predicted] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = u32_to_u8 ((scm_t_uint32 *) scm_i_string_wide_chars (str),
|
num_bytes_actual = num_bytes_predicted;
|
||||||
scm_i_string_length (str), buf, &actual_len);
|
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;
|
return (char *) ret;
|
||||||
|
|
||||||
/* An error: a bad codepoint. */
|
/* An error: a bad codepoint. */
|
||||||
|
|
|
@ -1078,6 +1078,74 @@ test_locale_strings ()
|
||||||
test_11 ("(string #\\f #\\nul)", NULL, 1, 0);
|
test_11 ("(string #\\f #\\nul)", NULL, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
test_is_exact ()
|
test_is_exact ()
|
||||||
{
|
{
|
||||||
|
@ -1122,6 +1190,7 @@ tests (void *data, int argc, char **argv)
|
||||||
test_from_double ();
|
test_from_double ();
|
||||||
test_to_double ();
|
test_to_double ();
|
||||||
test_locale_strings ();
|
test_locale_strings ();
|
||||||
|
test_to_utf8_stringn ();
|
||||||
test_is_exact ();
|
test_is_exact ();
|
||||||
test_is_inexact ();
|
test_is_inexact ();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue