diff --git a/src/util.c b/src/util.c index fada69c..ad128c3 100644 --- a/src/util.c +++ b/src/util.c @@ -1960,13 +1960,13 @@ char *format_timespan(char *buf, size_t l, usec_t t) { { "d", USEC_PER_DAY }, { "h", USEC_PER_HOUR }, { "min", USEC_PER_MINUTE }, - { "s", USEC_PER_SEC }, - { "ms", USEC_PER_MSEC }, - { "us", 1 }, }; unsigned i; char *p = buf; + int k; + int digits; + usec_t frac; assert(buf); assert(l > 0); @@ -1983,7 +1983,6 @@ char *format_timespan(char *buf, size_t l, usec_t t) { /* The result of this function can be parsed with parse_usec */ for (i = 0; i < ELEMENTSOF(table); i++) { - int k; size_t n; if (t < table[i].usec) @@ -2001,6 +2000,23 @@ char *format_timespan(char *buf, size_t l, usec_t t) { t %= table[i].usec; } + /* We have left a value between 0 and 59,999,999 (that is, 0s and 59.999999s) */ + if (t) { + if (t % USEC_PER_SEC == 0) { + digits = 1; + frac = 0; + } else if (t % USEC_PER_MSEC == 0) { + digits = 3; + frac = (t % USEC_PER_SEC) / USEC_PER_MSEC; + } else { + digits = 6; + frac = t % USEC_PER_SEC; + } + printf("DEBUG: digits=%d frac=%lld\n", digits, frac); + k = snprintf(p, l, "%s%llu.%0*llus", p > buf ? " " : "", (unsigned long long) (t / USEC_PER_SEC), digits, frac); + p += MIN((size_t) k, l); + } + *p = 0; return buf; @@ -2638,6 +2654,7 @@ int parse_usec(const char *t, usec_t *usec) { } table[] = { { "sec", USEC_PER_SEC }, { "s", USEC_PER_SEC }, + { ".", USEC_PER_SEC }, { "min", USEC_PER_MINUTE }, { "hr", USEC_PER_HOUR }, { "h", USEC_PER_HOUR }, @@ -2651,6 +2668,17 @@ int parse_usec(const char *t, usec_t *usec) { { "", USEC_PER_SEC }, }; + static const usec_t fract[] = { + USEC_PER_ZERO, + USEC_PER_SEC, + USEC_PER_DSEC, + USEC_PER_CSEC, + USEC_PER_MSEC, + USEC_PER_DMSEC, + USEC_PER_CMSEC, + USEC_PER_USEC + }; + const char *p; usec_t r = 0; @@ -2658,6 +2686,7 @@ int parse_usec(const char *t, usec_t *usec) { assert(usec); p = t; + char *last_e = ""; do { long long l; char *e; @@ -2679,7 +2708,13 @@ int parse_usec(const char *t, usec_t *usec) { for (i = 0; i < ELEMENTSOF(table); i++) if (startswith(e, table[i].suffix)) { - r += (usec_t) l * table[i].usec; + if (*last_e == '.') { + if (*e != 's' || e - last_e >= sizeof fract / sizeof fract[0]) + return -EINVAL; + r += (usec_t) l * fract[e - last_e]; + } else + r += (usec_t) l * table[i].usec; + last_e = e; p = e + strlen(table[i].suffix); break; } diff --git a/src/util.h b/src/util.h index 04afc73..14bbfa6 100644 --- a/src/util.h +++ b/src/util.h @@ -45,7 +45,13 @@ typedef struct dual_timestamp { #define MSEC_PER_SEC 1000ULL #define USEC_PER_SEC 1000000ULL +#define USEC_PER_DSEC (USEC_PER_SEC/10ULL) +#define USEC_PER_CSEC (USEC_PER_DSEC/10ULL) #define USEC_PER_MSEC 1000ULL +#define USEC_PER_DMSEC (USEC_PER_MSEC/10ULL) +#define USEC_PER_CMSEC (USEC_PER_DMSEC/10ULL) +#define USEC_PER_USEC 1ULL +#define USEC_PER_ZERO 0ULL #define NSEC_PER_SEC 1000000000ULL #define NSEC_PER_MSEC 1000000ULL #define NSEC_PER_USEC 1000ULL