7 static gint exit_status = 0;
10 croak (char *format, ...)
14 va_start (va, format);
15 vfprintf (stderr, format, va);
22 fail (char *format, ...)
26 va_start (va, format);
27 vfprintf (stderr, format, va);
43 ucs4_equal (gunichar *a, gunichar *b)
45 while (*a && *b && (*a == *b))
55 utf16_equal (gunichar2 *a, gunichar2 *b)
57 while (*a && *b && (*a == *b))
67 utf16_count (gunichar2 *a)
85 gboolean is_valid = g_utf8_validate (utf8, -1, &end);
87 gint items_read, items_written;
94 fail ("line %d: valid but g_utf8_validate returned FALSE\n", line);
104 fail ("line %d: invalid but g_utf8_validate returned TRUE\n", line);
110 if (status == INCOMPLETE)
112 gunichar *ucs4_result;
114 ucs4_result = g_utf8_to_ucs4 (utf8, -1, NULL, NULL, &error);
116 if (!error || !g_error_matches (error, G_CONVERT_ERROR, G_CONVERT_ERROR_PARTIAL_INPUT))
118 fail ("line %d: incomplete input not properly detected\n", line);
121 g_clear_error (&error);
123 ucs4_result = g_utf8_to_ucs4 (utf8, -1, &items_read, NULL, &error);
125 if (!ucs4_result || items_read == strlen (utf8))
127 fail ("line %d: incomplete input not properly detected\n", line);
131 g_free (ucs4_result);
134 if (status == VALID || status == NOTUNICODE)
136 gunichar *ucs4_result;
139 ucs4_result = g_utf8_to_ucs4 (utf8, -1, &items_read, &items_written, &error);
142 fail ("line %d: conversion to ucs4 failed: %s\n", line, error->message);
146 if (!ucs4_equal (ucs4_result, ucs4) ||
147 items_read != strlen (utf8) ||
148 items_written != ucs4_len)
150 fail ("line %d: results of conversion to ucs4 do not match expected.\n", line);
154 g_free (ucs4_result);
156 ucs4_result = g_utf8_to_ucs4_fast (utf8, -1, &items_written);
158 if (!ucs4_equal (ucs4_result, ucs4) ||
159 items_written != ucs4_len)
161 fail ("line %d: results of conversion to ucs4 do not match expected.\n", line);
165 utf8_result = g_ucs4_to_utf8 (ucs4_result, -1, &items_read, &items_written, &error);
168 fail ("line %d: conversion back to utf8 failed: %s", line, error->message);
172 if (strcmp (utf8_result, utf8) != 0 ||
173 items_read != ucs4_len ||
174 items_written != strlen (utf8))
176 fail ("line %d: conversion back to utf8 did not match original\n", line);
180 g_free (utf8_result);
181 g_free (ucs4_result);
186 gunichar2 *utf16_expected_tmp;
187 gunichar2 *utf16_expected;
188 gunichar2 *utf16_from_utf8;
189 gunichar2 *utf16_from_ucs4;
190 gunichar *ucs4_result;
195 if (!(utf16_expected_tmp = (gunichar2 *)g_convert (utf8, -1, "UTF-16", "UTF-8",
196 NULL, &bytes_written, NULL)))
198 fail ("line %d: could not convert to UTF-16 via g_convert\n", line);
202 /* zero-terminate and remove BOM
204 n_chars = bytes_written / 2;
205 if (utf16_expected_tmp[0] == 0xfeff) /* BOM */
208 utf16_expected = g_new (gunichar2, n_chars + 1);
209 memcpy (utf16_expected, utf16_expected_tmp + 1, sizeof(gunichar2) * n_chars);
211 else if (utf16_expected_tmp[0] == 0xfffe) /* ANTI-BOM */
213 fail ("line %d: conversion via iconv to \"UTF-16\" is not native-endian\n");
218 utf16_expected = g_new (gunichar2, n_chars + 1);
219 memcpy (utf16_expected, utf16_expected_tmp, sizeof(gunichar2) * n_chars);
222 utf16_expected[n_chars] = '\0';
224 if (!(utf16_from_utf8 = g_utf8_to_utf16 (utf8, -1, &items_read, &items_written, &error)))
226 fail ("line %d: conversion to ucs16 failed: %s\n", line, error->message);
230 if (items_read != strlen (utf8) ||
231 utf16_count (utf16_from_utf8) != items_written)
233 fail ("line %d: length error in conversion to ucs16\n", line);
237 if (!(utf16_from_ucs4 = g_ucs4_to_utf16 (ucs4, -1, &items_read, &items_written, &error)))
239 fail ("line %d: conversion to ucs16 failed: %s\n", line, error->message);
243 if (items_read != ucs4_len ||
244 utf16_count (utf16_from_ucs4) != items_written)
246 fail ("line %d: length error in conversion to ucs16\n", line);
250 if (!utf16_equal (utf16_from_utf8, utf16_expected) ||
251 !utf16_equal (utf16_from_ucs4, utf16_expected))
253 fail ("line %d: results of conversion to ucs16 do not match\n", line);
257 if (!(utf8_result = g_utf16_to_utf8 (utf16_from_utf8, -1, &items_read, &items_written, &error)))
259 fail ("line %d: conversion back to utf8 failed: %s\n", line, error->message);
263 if (items_read != utf16_count (utf16_from_utf8) ||
264 items_written != strlen (utf8))
266 fail ("line %d: length error in conversion from ucs16 to utf8\n", line);
270 if (!(ucs4_result = g_utf16_to_ucs4 (utf16_from_ucs4, -1, &items_read, &items_written, &error)))
272 fail ("line %d: conversion back to utf8/ucs4 failed\n", line);
276 if (items_read != utf16_count (utf16_from_utf8) ||
277 items_written != ucs4_len)
279 fail ("line %d: length error in conversion from ucs16 to ucs4\n", line);
283 if (strcmp (utf8, utf8_result) != 0 ||
284 !ucs4_equal (ucs4, ucs4_result))
286 fail ("line %d: conversion back to utf8/ucs4 did not match original\n", line);
290 g_free (utf16_expected_tmp);
291 g_free (utf16_expected);
292 g_free (utf16_from_utf8);
293 g_free (utf16_from_ucs4);
294 g_free (utf8_result);
295 g_free (ucs4_result);
300 main (int argc, char **argv)
302 gchar *srcdir = getenv ("srcdir");
305 GError *error = NULL;
310 gint start_line = 0; /* Quiet GCC */
311 gchar *utf8 = NULL; /* Quiet GCC */
313 Status status = VALID; /* Quiet GCC */
318 testfile = g_strconcat (srcdir, "/", "utf8.txt", NULL);
320 g_file_get_contents (testfile, &contents, NULL, &error);
322 croak ("Cannot open utf8.txt: %s", error->message);
324 ucs4 = g_array_new (TRUE, FALSE, sizeof(gunichar));
328 /* Loop over lines */
331 while (*p && (*p == ' ' || *p == '\t'))
335 while (*end && *end != '\n')
338 if (!*p || *p == '#' || *p == '\n')
341 tmp = g_strstrip (g_strndup (p, end - p));
354 if (!strcmp (tmp, "VALID"))
356 else if (!strcmp (tmp, "INCOMPLETE"))
358 else if (!strcmp (tmp, "NOTUNICODE"))
360 else if (!strcmp (tmp, "OVERLONG"))
362 else if (!strcmp (tmp, "MALFORMED"))
365 croak ("Invalid status on line %d\n", line);
367 if (status != VALID && status != NOTUNICODE)
368 state++; /* No UCS-4 data */
375 p = strtok (tmp, " \t");
380 gunichar ch = strtoul (p, &endptr, 16);
382 croak ("Invalid UCS-4 character on line %d\n", line);
384 g_array_append_val (ucs4, ch);
386 p = strtok (NULL, " \t");
393 state = (state + 1) % 3;
397 process (start_line, utf8, status, (gunichar *)ucs4->data, ucs4->len);
398 g_array_set_size (ucs4, 0);
404 if (*p && *p == '\n')