mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-08 10:08:05 +02:00
util: add safe_atod for locale-independent conversion
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit d6020d7ab2)
This commit is contained in:
parent
bfff1ab3ef
commit
ed4d674ca2
3 changed files with 81 additions and 13 deletions
|
|
@ -248,21 +248,10 @@ parse_mouse_wheel_click_angle_property(const char *prop)
|
||||||
double
|
double
|
||||||
parse_trackpoint_accel_property(const char *prop)
|
parse_trackpoint_accel_property(const char *prop)
|
||||||
{
|
{
|
||||||
locale_t c_locale;
|
|
||||||
double accel;
|
double accel;
|
||||||
char *endp;
|
|
||||||
|
|
||||||
/* Create a "C" locale to force strtod to use '.' as separator */
|
if (!safe_atod(prop, &accel))
|
||||||
c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
accel = 0.0;
|
||||||
if (c_locale == (locale_t)0)
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
accel = strtod_l(prop, &endp, c_locale);
|
|
||||||
|
|
||||||
freelocale(c_locale);
|
|
||||||
|
|
||||||
if (*endp != '\0')
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
return accel;
|
return accel;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -427,4 +428,32 @@ safe_atoi(const char *str, int *val)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
safe_atod(const char *str, double *val)
|
||||||
|
{
|
||||||
|
char *endptr;
|
||||||
|
double v;
|
||||||
|
locale_t c_locale;
|
||||||
|
|
||||||
|
/* Create a "C" locale to force strtod to use '.' as separator */
|
||||||
|
c_locale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||||
|
if (c_locale == (locale_t)0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
v = strtod_l(str, &endptr, c_locale);
|
||||||
|
freelocale(c_locale);
|
||||||
|
if (errno > 0)
|
||||||
|
return false;
|
||||||
|
if (str == endptr)
|
||||||
|
return false;
|
||||||
|
if (*str != '\0' && *endptr != '\0')
|
||||||
|
return false;
|
||||||
|
if (isnan(v) || isinf(v))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*val = v;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* LIBINPUT_UTIL_H */
|
#endif /* LIBINPUT_UTIL_H */
|
||||||
|
|
|
||||||
50
test/misc.c
50
test/misc.c
|
|
@ -861,6 +861,55 @@ START_TEST(time_conversion)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
struct atod_test {
|
||||||
|
char *str;
|
||||||
|
bool success;
|
||||||
|
double val;
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(safe_atod_test)
|
||||||
|
{
|
||||||
|
struct atod_test tests[] = {
|
||||||
|
{ "10", true, 10 },
|
||||||
|
{ "20", true, 20 },
|
||||||
|
{ "-1", true, -1 },
|
||||||
|
{ "2147483647", true, 2147483647 },
|
||||||
|
{ "-2147483648", true, -2147483648 },
|
||||||
|
{ "4294967295", true, 4294967295 },
|
||||||
|
{ "0x0", true, 0 },
|
||||||
|
{ "0x10", true, 0x10 },
|
||||||
|
{ "0xaf", true, 0xaf },
|
||||||
|
{ "x80", false, 0 },
|
||||||
|
{ "0.0", true, 0.0 },
|
||||||
|
{ "0.1", true, 0.1 },
|
||||||
|
{ "1.2", true, 1.2 },
|
||||||
|
{ "-324.9", true, -324.9 },
|
||||||
|
{ "9324.9", true, 9324.9 },
|
||||||
|
{ "NAN", false, 0 },
|
||||||
|
{ "INFINITY", false, 0 },
|
||||||
|
{ "-10x10", false, 0 },
|
||||||
|
{ "1x-99", false, 0 },
|
||||||
|
{ "", false, 0 },
|
||||||
|
{ "abd", false, 0 },
|
||||||
|
{ "xabd", false, 0 },
|
||||||
|
{ "0x0x", false, 0 },
|
||||||
|
{ NULL, false, 0 }
|
||||||
|
};
|
||||||
|
double v;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
for (int i = 0; tests[i].str != NULL; i++) {
|
||||||
|
v = 0xad;
|
||||||
|
success = safe_atod(tests[i].str, &v);
|
||||||
|
ck_assert(success == tests[i].success);
|
||||||
|
if (success)
|
||||||
|
ck_assert_int_eq(v, tests[i].val);
|
||||||
|
else
|
||||||
|
ck_assert_int_eq(v, 0xad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
static int open_restricted_leak(const char *path, int flags, void *data)
|
static int open_restricted_leak(const char *path, int flags, void *data)
|
||||||
{
|
{
|
||||||
return *(int*)data;
|
return *(int*)data;
|
||||||
|
|
@ -988,6 +1037,7 @@ litest_setup_tests_misc(void)
|
||||||
litest_add_no_device("misc:parser", wheel_click_count_parser);
|
litest_add_no_device("misc:parser", wheel_click_count_parser);
|
||||||
litest_add_no_device("misc:parser", trackpoint_accel_parser);
|
litest_add_no_device("misc:parser", trackpoint_accel_parser);
|
||||||
litest_add_no_device("misc:parser", dimension_prop_parser);
|
litest_add_no_device("misc:parser", dimension_prop_parser);
|
||||||
|
litest_add_no_device("misc:parser", safe_atod_test);
|
||||||
litest_add_no_device("misc:time", time_conversion);
|
litest_add_no_device("misc:time", time_conversion);
|
||||||
|
|
||||||
litest_add_no_device("misc:fd", fd_no_event_leak);
|
litest_add_no_device("misc:fd", fd_no_event_leak);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue