commit: e450d99b5382edf35a5e9e9e66fab0c8686e8cc6
parent 1a622d996f83e14a43b84c0cc572eaf7650961e6
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Thu, 26 Sep 2024 10:05:57 +0200
lib/strtodur: fix fractional + suffix
Diffstat:
2 files changed, 46 insertions(+), 33 deletions(-)
diff --git a/lib/strtodur.c b/lib/strtodur.c
@@ -12,16 +12,17 @@
int
strtodur(char *s, struct timespec *dur)
{
- if(s == 0 || s[0] == 0) return 0;
+ if(s == 0 || s[0] == '\0') return 0;
assert(dur);
- int parsed = 0;
+ float in = 0.0;
+
if(s[0] != '.' && s[0] != ',')
{
+ int parsed = 0;
assert(errno == 0);
- int ret = sscanf(s, "%10ld%n", &dur->tv_sec, &parsed);
- if(ret < 1)
+ if(sscanf(s, "%10f%n", &in, &parsed) < 1)
{
if(errno == 0)
{
@@ -36,17 +37,14 @@ strtodur(char *s, struct timespec *dur)
}
s += parsed;
-
- if(s[0] == 0) return 0;
}
- if(s[0] == '.' || s[0] == ',')
+ if((s[0] == '.' || s[0] == ',') && s[1] != '\0')
{
float fraction = 0.0;
- if(s[1] == 0) return 0;
if(s[0] == ',') s[0] = '.';
- parsed = 0;
+ int parsed = 0;
assert(errno == 0);
if(sscanf(s, "%10f%n", &fraction, &parsed) < 1)
{
@@ -62,35 +60,40 @@ strtodur(char *s, struct timespec *dur)
return -1;
}
- dur->tv_nsec = fraction * 1000000000;
+ in += fraction;
s += parsed;
}
- if(s[0] == 0) return 0;
-
- if(s[1] != 0)
+ if(s[0] != '\0' && s[0] != ',' && s[0] != '.')
{
- fprintf(stderr, "strtodur: error: suffix '%s' is too long, should be only one character\n", s);
- return -1;
- }
+ if(s[1] != '\0')
+ {
+ fprintf(
+ stderr, "strtodur: error: suffix '%s' is too long, should be only one character\n", s);
+ return -1;
+ }
- switch(s[0])
- {
- case 's': // seconds
- break;
- case 'm': // minutes
- dur->tv_sec *= 60;
- break;
- case 'h': // hours
- dur->tv_sec *= 60 * 60;
- break;
- case 'd': // days
- dur->tv_sec *= 24 * 60 * 60;
- break;
- default:
- fprintf(stderr, "strtodur: error: Unknown suffix %c\n", s[0]);
- 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, "strtodur: error: Unknown suffix '%c'\n", s[0]);
+ return -1;
+ }
}
+ dur->tv_sec = in;
+ dur->tv_nsec = (in - dur->tv_sec) * 1000000000;
+
return 0;
}
diff --git a/test-lib/strtodur.c b/test-lib/strtodur.c
@@ -43,7 +43,7 @@ t_strtodur(char *str, time_t ex_sec, long ex_nsec)
int
main(void)
{
- int plan = 8;
+ int plan = 16;
printf("1..%d\n", plan);
// TODO: Capture errors, say with open_memstream(3)
@@ -59,6 +59,16 @@ main(void)
t_strtodur((char *)".1", 0, 1000000000 * 0.1);
t_strtodur((char *)"0.1", 0, 1000000000 * 0.1);
+ t_strtodur((char *)"1s", 1, 0);
+ t_strtodur((char *)"1m", 60, 0);
+ t_strtodur((char *)"1h", 60 * 60, 0);
+ t_strtodur((char *)"1d", 60 * 60 * 24, 0);
+
+ t_strtodur((char *)"1.5s", 1, 1000000000 * 0.5);
+ t_strtodur((char *)"1.5m", 1.5 * 60, 0);
+ t_strtodur((char *)"1.5h", 1.5 * 60 * 60, 0);
+ t_strtodur((char *)"1.5d", 1.5 * 60 * 60 * 24, 0);
+
assert(counter == plan);
return err;
}