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/time-util.c | |
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/time-util.c')
-rw-r--r-- | src/shared/time-util.c | 90 |
1 files changed, 78 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; |