#include <err.h>
#include <stdlib.h>
#include <xlocale.h>
#include <locale.h>
#include <sys/sysmacros.h>
#include <sys/debug.h>
#include <stdbool.h>
#include <string.h>
static struct test_locale {
char *name;
char *number;
} locales[] = {
{ "C.UTF-8", "1.5"},
{"ja_JP.UTF-8", "1.5"},
{"de_DE.UTF-8", "1,5"},
{"en_US.UTF-8", "1.5"},
{"en_GB.UTF-8", "1.5" },
};
bool
test_locale(char *name, char *number)
{
bool result_ok = true;
const float expected_f = 1.5;
const double expected_d = 1.5;
const long double expected_ld = 1.5;
char *expected_end = number + strlen(number);
char *actual_end;
float actual_f;
double actual_d;
long double actual_ld;
locale_t loc = newlocale(LC_ALL_MASK, name, NULL);
if (loc == NULL) {
err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to "
"construct locale %s", name);
}
#define CHECK_END(fn) \
if (actual_end != expected_end) { \
warn("Locale %s, function %s: consumed %td characters" \
" (%td expected)", name, #fn, \
actual_end - number, expected_end - number); \
result_ok = false; \
}
actual_f = strtof_l(number, &actual_end, loc);
if (actual_f != expected_f) {
result_ok = false;
warn("Locale %s: strtof_l: mismatched value %f vs %f",
name, actual_f, expected_f);
}
CHECK_END(strtof_l);
actual_d = strtod_l(number, &actual_end, loc);
if (actual_d != expected_d) {
result_ok = false;
warn("Locale %s: strtod_l: mismatched value %f vs %f",
name, actual_d, expected_d);
}
CHECK_END(strtod_l);
actual_ld = strtold_l(number, &actual_end, loc);
if (actual_ld != expected_ld) {
result_ok = false;
warn("Locale %s: strtold_l: mismatched value %Lf vs %Lf",
name, actual_ld, expected_ld);
}
CHECK_END(strtold_l);
if (uselocale(loc) == NULL) {
err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to "
"set locale %s", name);
}
actual_f = strtod(number, &actual_end);
if (actual_f != expected_f) {
result_ok = false;
warn("Locale %s: strtof: mismatched value %f vs %f",
name, actual_f, expected_f);
}
CHECK_END(strtof);
actual_d = strtod(number, &actual_end);
if (actual_d != expected_d) {
result_ok = false;
warn("Locale %s: strtod: mismatched value %f vs %f",
name, actual_d, expected_d);
}
CHECK_END(strtod);
actual_ld = strtold(number, &actual_end);
if (actual_ld != expected_ld) {
result_ok = false;
warn("Locale %s: strtold: mismatched value %Lf vs %Lf",
name, actual_ld, expected_ld);
}
CHECK_END(strtold);
return (result_ok);
}
int
main(void)
{
int ret = EXIT_SUCCESS;
for (size_t i = 0; i < ARRAY_SIZE(locales); i++) {
if (!test_locale(locales[i].name, locales[i].number))
ret = EXIT_FAILURE;
}
if (ret == EXIT_SUCCESS) {
(void) printf("All tests completed successfully\n");
}
return (ret);
}