summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-04-03 22:58:41 +0200
committerLennart Poettering <lennart@poettering.net>2013-04-03 23:00:08 +0200
commitcb0dac0548e5e51ba21618bfe4711dc1a2bbcfb5 (patch)
treea8b69c2b2507378c89cdb37ebe0683da34832c5e /src/shared
parentd3b9e0ff4e9f1b0bb328dc57ca5507bac48a6615 (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.c90
-rw-r--r--src/shared/time-util.h1
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;