From b4b3b41989522a455198514a8a6f3c6df04dfd06 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Mon, 17 Aug 2020 15:28:00 +0300 Subject: [PATCH] lib: Add str_to_timeval() --- src/lib/test-time-util.c | 39 +++++++++++++++++++++++++++++++++++++++ src/lib/time-util.c | 28 ++++++++++++++++++++++++++++ src/lib/time-util.h | 7 +++++++ 3 files changed, 74 insertions(+) diff --git a/src/lib/test-time-util.c b/src/lib/test-time-util.c index 823f76d880..cfa322048e 100644 --- a/src/lib/test-time-util.c +++ b/src/lib/test-time-util.c @@ -354,6 +354,44 @@ static void test_micro_nanoseconds(void) test_end(); } +static void test_str_to_timeval(void) +{ + struct { + const char *str; + unsigned int tv_sec, tv_usec; + } tests[] = { + { "0", 0, 0 }, + { "0.0", 0, 0 }, + { "0.000000", 0, 0 }, + { "0.1", 0, 100000 }, + { "0.100000", 0, 100000 }, + { "0.000001", 0, 1 }, + { "0.100000", 0, 100000 }, + { "2147483647", 2147483647, 0 }, + { "2147483647.999999", 2147483647, 999999 }, + }; + const char *test_failures[] = { + "", + "0.", + "0.0000000", + "1234.-1", + "1234.x", + "x", + "x.100", + }; + struct timeval tv; + + test_begin("str_to_timeval"); + for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) { + test_assert_idx(str_to_timeval(tests[i].str, &tv) == 0, i); + test_assert_idx(tv.tv_sec == tests[i].tv_sec, i); + test_assert_idx(tv.tv_usec == tests[i].tv_usec, i); + } + for (unsigned int i = 0; i < N_ELEMENTS(test_failures); i++) + test_assert_idx(str_to_timeval(test_failures[i], &tv) == -1, i); + test_end(); +} + void test_time_util(void) { test_timeval_cmp(); @@ -363,4 +401,5 @@ void test_time_util(void) test_strftime_now(); test_strftime_fixed(); test_micro_nanoseconds(); + test_str_to_timeval(); } diff --git a/src/lib/time-util.c b/src/lib/time-util.c index 7e269cd38b..3168c6df8e 100644 --- a/src/lib/time-util.c +++ b/src/lib/time-util.c @@ -131,3 +131,31 @@ const char *t_strfgmtime(const char *fmt, time_t t) { return strftime_real(fmt, gmtime(&t)); } + +int str_to_timeval(const char *str, struct timeval *tv_r) +{ + tv_r->tv_usec = 0; + + const char *p = strchr(str, '.'); + if (p == NULL) + return str_to_time(str, &tv_r->tv_sec); + + int ret; + T_BEGIN { + ret = str_to_time(t_strdup_until(str, p++), &tv_r->tv_sec); + } T_END; + if (ret < 0 || p[0] == '\0') + return -1; + + unsigned int len = strlen(p); + if (len > 6) + return -1; /* we don't support sub-microseconds */ + char usecs_str[7] = "000000"; + memcpy(usecs_str, p, len); + + unsigned int usec; + if (str_to_uint(usecs_str, &usec) < 0) + return -1; + tv_r->tv_usec = usec; + return 0; +} diff --git a/src/lib/time-util.h b/src/lib/time-util.h index d872158527..31bf9ecd78 100644 --- a/src/lib/time-util.h +++ b/src/lib/time-util.h @@ -77,4 +77,11 @@ const char *t_strftime(const char *fmt, const struct tm *tm) ATTR_STRFTIME(1); const char *t_strflocaltime(const char *fmt, time_t t) ATTR_STRFTIME(1); const char *t_strfgmtime(const char *fmt, time_t t) ATTR_STRFTIME(1); +/* Parse string as [.] into timeval. must not + have higher precision time, i.e. a maximum of 6 digits is allowed. Note that + ".1" is handled as ".1000000" so the string should have been written using + "%06u" printf format. */ +int str_to_timeval(const char *str, struct timeval *tv_r) + ATTR_WARN_UNUSED_RESULT; + #endif -- 2.47.3