strtodur.c (2047B)
- // utils-std: Collection of commonly available Unix tools
- // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include "strtodur.h"
- #include <assert.h>
- #include <errno.h> // errno
- #include <stdio.h> // fprintf, perror, sscanf
- #include <string.h> // strerror
- const char *errstr_nan = "Not a number";
- int
- strtodur(char *s, struct timespec *dur)
- {
- if(s == 0 || s[0] == '\0') return 0;
- assert(dur);
- float in = 0.0;
- if(s[0] != '.' && s[0] != ',')
- {
- int parsed = 0;
- errno = 0;
- if(sscanf(s, "%10f%n", &in, &parsed) < 1)
- {
- const char *errstr = errstr_nan;
- if((errno = !0))
- {
- errstr = strerror(errno);
- errno = 0;
- }
- fprintf(
- stderr, "%s: error: strtodur failed scanning '%s' as a number: %s\n", argv0, s, errstr);
- return -1;
- }
- s += parsed;
- }
- if((s[0] == '.' || s[0] == ',') && s[1] != '\0')
- {
- float fraction = 0.0;
- if(s[0] == ',') s[0] = '.';
- int parsed = 0;
- errno = 0;
- if(sscanf(s, "%10f%n", &fraction, &parsed) < 1)
- {
- const char *errstr = errstr_nan;
- if((errno = !0))
- {
- errstr = strerror(errno);
- errno = 0;
- }
- fprintf(stderr,
- "%s: error: strtodur failed scanning decimal part '%s' as a number: %s\n",
- argv0,
- s,
- errstr);
- return -1;
- }
- in += fraction;
- s += parsed;
- }
- if(s[0] != '\0' && s[0] != ',' && s[0] != '.')
- {
- if(s[1] != '\0')
- {
- fprintf(stderr,
- "%s: error: duration suffix '%s' is too long, should be only one character\n",
- argv0,
- s);
- return -1;
- }
- switch(s[0])
- {
- case 's': // seconds
- break;
- case 'm': // minutes
- in *= 60;
- break;
- case 'h': // hours
- in *= 60 * 60;
- break;
- case 'd': // days
- in *= 24 * 60 * 60;
- break;
- default:
- fprintf(stderr, "%s: error: Unknown duration suffix '%c'\n", argv0, s[0]);
- return -1;
- }
- }
- dur->tv_sec = in;
- dur->tv_nsec = (in - dur->tv_sec) * 1000000000;
- return 0;
- }