]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Add str_to_timeval()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 17 Aug 2020 12:28:00 +0000 (15:28 +0300)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Fri, 21 Aug 2020 08:51:13 +0000 (08:51 +0000)
src/lib/test-time-util.c
src/lib/time-util.c
src/lib/time-util.h

index 823f76d88015ada71ae10e7b85abd3789ae36591..cfa322048e5009450735ec81daf5d04c03873ab6 100644 (file)
@@ -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();
 }
index 7e269cd38b0f9f274b50bad5b5dee5bfdfb5aa1b..3168c6df8eccbc83004888d5cd80ac02f8686e62 100644 (file)
@@ -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;
+}
index d8721585276e0a4d1901efb5a508278afdc4e590..31bf9ecd785261aba164511e48cf083772b1cae8 100644 (file)
@@ -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 <unix timestamp>[.<usecs>] into timeval. <usecs> 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