From cb0dac0548e5e51ba21618bfe4711dc1a2bbcfb5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 3 Apr 2013 22:58:41 +0200 Subject: time: add suppot for fractional time specifications We can now parse "0.5s" as the same as "500ms". In fact, we can parse "3.45years" correctly, too, and any other unit and fraction length. --- src/shared/time-util.c | 90 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 12 deletions(-) (limited to 'src/shared/time-util.c') diff --git a/src/shared/time-util.c b/src/shared/time-util.c index e27aaf6c6a..476b847ead 100644 --- a/src/shared/time-util.c +++ b/src/shared/time-util.c @@ -534,15 +534,25 @@ int parse_sec(const char *t, usec_t *usec) { const char *p; usec_t r = 0; + bool something = false; assert(t); assert(usec); p = t; - do { - long long l; + for (;;) { + long long l, z = 0; char *e; - unsigned i; + unsigned i, n = 0; + + p += strspn(p, WHITESPACE); + + if (*p == 0) { + if (!something) + return -EINVAL; + + break; + } errno = 0; l = strtoll(p, &e, 10); @@ -553,22 +563,45 @@ int parse_sec(const char *t, usec_t *usec) { if (l < 0) return -ERANGE; - if (e == p) + if (*e == '.') { + char *b = e + 1; + + errno = 0; + z = strtoll(b, &e, 10); + if (errno > 0) + return -errno; + + if (z < 0) + return -ERANGE; + + if (e == b) + return -EINVAL; + + n = e - b; + + } else if (e == p) return -EINVAL; e += strspn(e, WHITESPACE); for (i = 0; i < ELEMENTSOF(table); i++) if (startswith(e, table[i].suffix)) { - r += (usec_t) l * table[i].usec; + usec_t k = (usec_t) z * table[i].usec; + + for (; n > 0; n--) + k /= 10; + + r += (usec_t) l * table[i].usec + k; p = e + strlen(table[i].suffix); + + something = true; break; } if (i >= ELEMENTSOF(table)) return -EINVAL; - } while (*p != 0); + } *usec = r; @@ -614,15 +647,25 @@ int parse_nsec(const char *t, nsec_t *nsec) { const char *p; nsec_t r = 0; + bool something = false; assert(t); assert(nsec); p = t; - do { - long long l; + for (;;) { + long long l, z = 0; char *e; - unsigned i; + unsigned i, n = 0; + + p += strspn(p, WHITESPACE); + + if (*p == 0) { + if (!something) + return -EINVAL; + + break; + } errno = 0; l = strtoll(p, &e, 10); @@ -633,22 +676,45 @@ int parse_nsec(const char *t, nsec_t *nsec) { if (l < 0) return -ERANGE; - if (e == p) + if (*e == '.') { + char *b = e + 1; + + errno = 0; + z = strtoll(b, &e, 10); + if (errno > 0) + return -errno; + + if (z < 0) + return -ERANGE; + + if (e == b) + return -EINVAL; + + n = e - b; + + } else if (e == p) return -EINVAL; e += strspn(e, WHITESPACE); for (i = 0; i < ELEMENTSOF(table); i++) if (startswith(e, table[i].suffix)) { - r += (nsec_t) l * table[i].nsec; + nsec_t k = (nsec_t) z * table[i].nsec; + + for (; n > 0; n--) + k /= 10; + + r += (nsec_t) l * table[i].nsec + k; p = e + strlen(table[i].suffix); + + something = true; break; } if (i >= ELEMENTSOF(table)) return -EINVAL; - } while (*p != 0); + } *nsec = r; -- cgit v1.2.3-54-g00ecf