1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-11 09:18:07 +03:00

time-util: add parse_time(), which is like parse_sec() but allows specification of default time unit if none is specified

This is useful if we want to parse RLIMIT_RTTIME values where the common
UNIX syntax is without any units but refers to a non-second unit (µs in
this case), but where we want to allow specification of units.
This commit is contained in:
Lennart Poettering 2015-11-10 16:04:37 +01:00
parent 75eb615480
commit 519cffec89
4 changed files with 47 additions and 14 deletions

View File

@ -562,7 +562,7 @@ static int parse_date(const char **p, CalendarSpec *c) {
return -EINVAL;
}
static int parse_time(const char **p, CalendarSpec *c) {
static int parse_calendar_time(const char **p, CalendarSpec *c) {
CalendarComponent *h = NULL, *m = NULL, *s = NULL;
const char *t;
int r;
@ -802,7 +802,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) {
if (r < 0)
goto fail;
r = parse_time(&p, c);
r = parse_calendar_time(&p, c);
if (r < 0)
goto fail;

View File

@ -705,7 +705,8 @@ finish:
return 0;
}
int parse_sec(const char *t, usec_t *usec) {
int parse_time(const char *t, usec_t *usec, usec_t default_unit) {
static const struct {
const char *suffix;
usec_t usec;
@ -737,7 +738,6 @@ int parse_sec(const char *t, usec_t *usec) {
{ "y", USEC_PER_YEAR },
{ "usec", 1ULL },
{ "us", 1ULL },
{ "", USEC_PER_SEC }, /* default is sec */
};
const char *p, *s;
@ -746,6 +746,7 @@ int parse_sec(const char *t, usec_t *usec) {
assert(t);
assert(usec);
assert(default_unit > 0);
p = t;
@ -764,6 +765,7 @@ int parse_sec(const char *t, usec_t *usec) {
long long l, z = 0;
char *e;
unsigned i, n = 0;
usec_t multiplier, k;
p += strspn(p, WHITESPACE);
@ -806,21 +808,24 @@ int parse_sec(const char *t, usec_t *usec) {
for (i = 0; i < ELEMENTSOF(table); i++)
if (startswith(e, table[i].suffix)) {
usec_t k = (usec_t) z * table[i].usec;
multiplier = table[i].usec;
p = e + strlen(table[i].suffix);
break;
}
if (i >= ELEMENTSOF(table)) {
multiplier = default_unit;
p = e;
}
something = true;
k = (usec_t) z * multiplier;
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;
r += (usec_t) l * multiplier + k;
}
*usec = r;
@ -828,6 +833,10 @@ int parse_sec(const char *t, usec_t *usec) {
return 0;
}
int parse_sec(const char *t, usec_t *usec) {
return parse_time(t, usec, USEC_PER_SEC);
}
int parse_nsec(const char *t, nsec_t *nsec) {
static const struct {
const char *suffix;

View File

@ -104,6 +104,7 @@ int dual_timestamp_deserialize(const char *value, dual_timestamp *t);
int parse_timestamp(const char *t, usec_t *usec);
int parse_sec(const char *t, usec_t *usec);
int parse_time(const char *t, usec_t *usec, usec_t default_unit);
int parse_nsec(const char *t, nsec_t *nsec);
bool ntp_synced(void);

View File

@ -57,6 +57,28 @@ static void test_parse_sec(void) {
assert_se(parse_sec(".3 infinity", &u) < 0);
}
static void test_parse_time(void) {
usec_t u;
assert_se(parse_time("5", &u, 1) >= 0);
assert_se(u == 5);
assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0);
assert_se(u == 5 * USEC_PER_MSEC);
assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
assert_se(parse_time("5s", &u, 1) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0);
assert_se(u == 5 * USEC_PER_SEC);
}
static void test_parse_nsec(void) {
nsec_t u;
@ -161,6 +183,7 @@ static void test_get_timezones(void) {
int main(int argc, char *argv[]) {
test_parse_sec();
test_parse_time();
test_parse_nsec();
test_format_timespan(1);
test_format_timespan(USEC_PER_MSEC);