[PATCH libinput 5/7] util: add safe_atod for locale-independent conversion
Peter Hutterer
peter.hutterer at who-t.net
Mon Nov 28 05:20:48 UTC 2016
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/libinput-util.c | 15 ++-------------
src/libinput-util.h | 29 +++++++++++++++++++++++++++++
test/misc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+), 13 deletions(-)
diff --git a/src/libinput-util.c b/src/libinput-util.c
index 6c051c3..4cf310b 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -248,21 +248,10 @@ parse_mouse_wheel_click_angle_property(const char *prop)
double
parse_trackpoint_accel_property(const char *prop)
{
- locale_t c_locale;
double accel;
- char *endp;
- /* 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 0.0;
-
- accel = strtod_l(prop, &endp, c_locale);
-
- freelocale(c_locale);
-
- if (*endp != '\0')
- return 0.0;
+ if (!safe_atod(prop, &accel))
+ accel = 0.0;
return accel;
}
diff --git a/src/libinput-util.h b/src/libinput-util.h
index a42643d..9b10e7d 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -30,6 +30,7 @@
#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <locale.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
@@ -427,4 +428,32 @@ safe_atoi(const char *str, int *val)
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 */
diff --git a/test/misc.c b/test/misc.c
index 95776f7..b514f90 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -902,6 +902,55 @@ START_TEST(safe_atoi_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)
{
return *(int*)data;
@@ -1030,6 +1079,7 @@ litest_setup_tests_misc(void)
litest_add_no_device("misc:parser", trackpoint_accel_parser);
litest_add_no_device("misc:parser", dimension_prop_parser);
litest_add_no_device("misc:parser", safe_atoi_test);
+ litest_add_no_device("misc:parser", safe_atod_test);
litest_add_no_device("misc:time", time_conversion);
litest_add_no_device("misc:fd", fd_no_event_leak);
--
2.9.3
More information about the wayland-devel
mailing list