diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-04-03 22:58:41 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-04-03 23:00:08 +0200 |
commit | cb0dac0548e5e51ba21618bfe4711dc1a2bbcfb5 (patch) | |
tree | a8b69c2b2507378c89cdb37ebe0683da34832c5e /src/shared | |
parent | d3b9e0ff4e9f1b0bb328dc57ca5507bac48a6615 (diff) |
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.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/time-util.c | 90 | ||||
-rw-r--r-- | src/shared/time-util.h | 1 |
2 files changed, 79 insertions, 12 deletions
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; diff --git a/src/shared/time-util.h b/src/shared/time-util.h index 2e3b0f5744..a02cdfc79f 100644 --- a/src/shared/time-util.h +++ b/src/shared/time-util.h @@ -22,6 +22,7 @@ ***/ #include <stdio.h> +#include <inttypes.h> typedef uint64_t usec_t; typedef uint64_t nsec_t; |