util.c: add parse_ts

* defs.h (parse_ts): New declaration.
* util.c (parse_ts): New function.
This commit is contained in:
Eugene Syromyatnikov
2018-09-02 20:04:27 +02:00
parent 7c7705fbc9
commit 32e987b87a
2 changed files with 67 additions and 0 deletions

1
defs.h
View File

@ -957,6 +957,7 @@ extern void ts_mul(struct timespec *, const struct timespec *, int);
extern void ts_div(struct timespec *, const struct timespec *, int);
extern void ts_min(struct timespec *, const struct timespec *, const struct timespec *);
extern void ts_max(struct timespec *, const struct timespec *, const struct timespec *);
extern int parse_ts(const char *s, struct timespec *t);
#ifdef ENABLE_STACKTRACE
extern void unwind_init(void);

66
util.c
View File

@ -44,6 +44,7 @@
#include <sys/uio.h>
#include "largefile_wrappers.h"
#include "string_to_uint.h"
#include "xlat.h"
#include "xstring.h"
@ -133,6 +134,71 @@ ts_max(struct timespec *tv, const struct timespec *a, const struct timespec *b)
}
}
int
parse_ts(const char *s, struct timespec *t)
{
enum { NS_IN_S = 1000000000 };
static const struct time_unit {
const char *s;
unsigned int mul;
} units[] = {
{ "", 1000 }, /* default is microseconds */
{ "s", 1000000000 },
{ "ms", 1000000 },
{ "us", 1000 },
{ "ns", 1 },
};
static const char float_accept[] = "eE.-+0123456789";
static const char int_accept[] = "+0123456789";
size_t float_len = strspn(s, float_accept);
size_t int_len = strspn(s, int_accept);
const struct time_unit *unit = NULL;
char *endptr = NULL;
double float_val;
long long int_val;
if (float_len > int_len) {
errno = 0;
float_val = strtod(s, &endptr);
if (endptr == s || errno)
return -1;
if (float_val < 0)
return -1;
} else {
int_val = string_to_uint_ex(s, &endptr, LLONG_MAX, "smun");
if (int_val < 0)
return -1;
}
for (size_t i = 0; i < ARRAY_SIZE(units); i++) {
if (strcmp(endptr, units[i].s))
continue;
unit = units + i;
break;
}
if (!unit)
return -1;
if (float_len > int_len) {
t->tv_sec = float_val / (NS_IN_S / unit->mul);
t->tv_nsec = ((uint64_t) ((float_val -
(t->tv_sec * (NS_IN_S / unit->mul)))
* unit->mul)) % NS_IN_S;
} else {
t->tv_sec = int_val / (NS_IN_S / unit->mul);
t->tv_nsec = (int_val % (NS_IN_S / unit->mul)) * unit->mul;
}
return 0;
}
#if !defined HAVE_STPCPY
char *
stpcpy(char *dst, const char *src)