Does what you expect, and returns false on errors.

Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 src/libinput-util.h | 23 +++++++++++++++++++++++
 test/misc.c         | 43 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/src/libinput-util.h b/src/libinput-util.h
index 53fe85f..04a454f 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -26,6 +26,7 @@
 #define LIBINPUT_UTIL_H
 
 #include <unistd.h>
+#include <limits.h>
 #include <math.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -352,4 +353,26 @@ us2ms(uint64_t us)
        return (uint32_t)(us / 1000);
 }
 
+static inline bool
+atoi_safe(const char *str, int *val)
+{
+       char *endptr;
+       long v;
+
+       if (!str)
+               return false;
+
+       v = strtol(str, &endptr, 0);
+
+       if (str == endptr || *endptr != '\0')
+               return false;
+
+       if (v > INT_MAX || v < INT_MIN)
+               return false;
+
+       *val = v;
+
+       return true;
+}
+
 #endif /* LIBINPUT_UTIL_H */
diff --git a/test/misc.c b/test/misc.c
index d880496..07cc21e 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -772,6 +772,46 @@ START_TEST(dimension_prop_parser)
 }
 END_TEST
 
+START_TEST(atoi_safe_test)
+{
+       struct test_case {
+               const char *str;
+               bool success;
+               int value;
+       } tests[] = {
+               { "0", true, 0 },
+               { "-1", true, -1 },
+               { "1", true, 1 },
+               { "0xffff", true, 0xffff },
+               { "077", true, 077 },
+               { "abc", false, 0 },
+               { "-1a", false, 0 },
+               { "b-1", false, 0 },
+               { "0xffffffffffffffff", false, 0 },
+               { "0xffffffff", false, 0 },
+               { NULL, false, 0 },
+       };
+       struct test_case *t = tests;
+       int val;
+       bool success;
+
+       while (t->str) {
+               val = 0x54;
+
+               success = atoi_safe(t->str, &val);
+               ck_assert_int_eq(success, t->success);
+               if (success)
+                       ck_assert_int_eq(val, t->value);
+               else
+                       ck_assert_int_eq(val, 0x54);
+               t++;
+       }
+
+       success = atoi_safe(NULL, &val);
+       ck_assert_int_eq(success, false);
+}
+END_TEST
+
 START_TEST(time_conversion)
 {
        ck_assert_int_eq(us(10), 10);
@@ -793,7 +833,6 @@ litest_setup_tests(void)
        litest_add_for_device("events:conversion", event_conversion_touch, 
LITEST_WACOM_TOUCH);
        litest_add_for_device("events:conversion", event_conversion_gesture, 
LITEST_BCM5974);
        litest_add_for_device("events:conversion", event_conversion_tablet, 
LITEST_WACOM_CINTIQ);
-       litest_add_no_device("bitfield_helpers", bitfield_helpers);
 
        litest_add_no_device("context:refcount", context_ref_counting);
        litest_add_no_device("config:status string", config_status_string);
@@ -805,4 +844,6 @@ litest_setup_tests(void)
        litest_add_no_device("misc:parser", trackpoint_accel_parser);
        litest_add_no_device("misc:parser", dimension_prop_parser);
        litest_add_no_device("misc:time", time_conversion);
+       litest_add_no_device("misc:helpers", bitfield_helpers);
+       litest_add_no_device("misc:helpers", atoi_safe_test);
 }
-- 
2.5.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to