commit: c37db06adf826bafee8bd4d42de58a4334c8315b
parent 2e7604927c930e333d46a4b4c061db4601b8b672
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Wed, 18 Jun 2025 12:00:21 +0200
Add strtodur
Diffstat:
6 files changed, 146 insertions(+), 15 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,4 +1,6 @@
# SPDX-FileCopyrightText: 2025 Haelwenn (lanodan) Monnier <contact+cmd-timer@hacktivis.me>
# SPDX-License-Identifier: MIT
+*.o
/timer
+/test_strtodur
diff --git a/Makefile b/Makefile
@@ -4,15 +4,23 @@
PREFIX ?= /usr/local
BINDIR ?= ${PREFIX}/bin
-timer: timer.c
- ${CC} -std=c99 ${CFLAGS} -o $@ $< ${LDFLAGS} $[LDSTATIC}
+TIMER_SRC_C = timer.c strtodur.o
+timer: ${TIMER_SRC_C} timer.h
+ ${CC} -std=c99 ${CFLAGS} -o $@ ${TIMER_SRC_C} ${LDFLAGS} ${LDSTATIC}
+
+TEST_STRTODUR_SRC_C = test_strtodur.c strtodur.o
+test_strtodur: ${TEST_STRTODUR_SRC_C} timer.h
+ ${CC} -std=c99 ${CFLAGS} -o $@ ${TEST_STRTODUR_SRC_C} ${LDFLAGS} ${LDSTATIC}
+
+check: test_strtodur
+ ./test_strtodur
clean:
- rm -f timer
+ rm -f timer test_strtodur strtodur.o
.PHONY: format
format:
- clang-format -style=file -assume-filename=.clang-format -i timer.c
+ clang-format -style=file -assume-filename=.clang-format -i *.c *.h
.PHONY: install
install:
diff --git a/strtodur.c b/strtodur.c
@@ -0,0 +1,65 @@
+// SPDX-FileCopyrightText: 2025 Haelwenn (lanodan) Monnier <contact+cmd-timer@hacktivis.me>
+// SPDX-License-Identifier: MIT
+
+#define _POSIX_C_SOURCE 200809L
+#include "timer.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+unsigned long
+strtodur(char *s)
+{
+ if(s == 0 || s[0] == '\0') return 0;
+
+ unsigned long dur = 0;
+
+ while(*s != '\0')
+ {
+ char *end = NULL;
+ errno = 0;
+ unsigned long tmp = strtoul(s, &end, 0);
+ if(errno != 0)
+ {
+ fprintf(stderr,
+ "timer: error: Failed parsing argument '%s' as integer: %s\n",
+ s,
+ strerror(errno));
+ return 1;
+ }
+
+ if(end)
+ {
+ s = end;
+
+ if(s[0] != '\0')
+ {
+ switch(s[0])
+ {
+ case 's': // seconds
+ break;
+ case 'm': // minutes
+ tmp *= 60;
+ break;
+ case 'h': // hours
+ tmp *= 60 * 60;
+ break;
+ case 'd': // days
+ tmp *= 24 * 60 * 60;
+ break;
+ default:
+ fprintf(stderr, "timer: error: Unknown duration suffix '%c'\n", s[0]);
+ return -1;
+ }
+
+ s++;
+ }
+ }
+
+ dur += tmp;
+ }
+
+ return dur;
+}
diff --git a/test_strtodur.c b/test_strtodur.c
@@ -0,0 +1,60 @@
+// SPDX-FileCopyrightText: 2025 Haelwenn (lanodan) Monnier <contact+cmd-timer@hacktivis.me>
+// SPDX-License-Identifier: MIT
+
+#define _POSIX_C_SOURCE 200809L
+#include "timer.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+int counter = 0;
+int err = 0;
+
+static void
+t(char *str, unsigned long exp)
+{
+ int id = ++counter;
+
+ unsigned long res = strtodur(str);
+ if(res == exp)
+ {
+ printf("ok %d - %s -> %ld\n", id, str, res);
+ return;
+ }
+
+ err = 1;
+ printf("not ok %d - %s -> %ld\n", id, str, res);
+ printf("# Expected: %ld\n", exp);
+}
+
+int
+main()
+{
+ int plan = 13;
+ printf("1..%d\n", plan);
+
+#define T_MIN 60
+#define T_HOUR 60 * T_MIN
+#define T_DAY 24 * T_HOUR
+
+ t(NULL, 0);
+ t("", 0);
+
+ t("5", 5);
+ t("5s", 5);
+
+ t("5m", 5 * T_MIN);
+ t("5m5s", (5 * T_MIN) + 5);
+
+ t("5h", 5 * T_HOUR);
+ t("5h5m", (5 * T_HOUR) + (5 * T_MIN));
+ t("5h5m5s", (5 * T_HOUR) + (5 * T_MIN) + 5);
+
+ t("5d", 5 * T_DAY);
+ t("5d5h", (5 * T_DAY) + (5 * T_HOUR));
+ t("5d5h5m", (5 * T_DAY) + (5 * T_HOUR) + (5 * T_MIN));
+ t("5d5h5m5s", (5 * T_DAY) + (5 * T_HOUR) + (5 * T_MIN) + 5);
+
+ assert(counter == plan);
+ return err;
+}
diff --git a/timer.c b/timer.c
@@ -2,6 +2,8 @@
// SPDX-License-Identifier: MIT
#define _POSIX_C_SOURCE 200809L
+#include "timer.h"
+
#include <errno.h>
#include <limits.h> // UINT_MAX
#include <signal.h> // sigaction
@@ -47,17 +49,7 @@ main(int argc, char *argv[])
bad_usage();
}
- char *durend = NULL;
- errno = 0;
- unsigned long dur = strtoul(*argv, &durend, 0);
- if(errno != 0)
- {
- fprintf(stderr,
- "timer: error: Failed parsing argument '%s' as integer: %s\n",
- *argv,
- strerror(errno));
- return 1;
- }
+ unsigned long dur = strtodur(*argv);
if(dur == 0)
{
diff --git a/timer.h b/timer.h
@@ -0,0 +1,4 @@
+// SPDX-FileCopyrightText: 2025 Haelwenn (lanodan) Monnier <contact+cmd-timer@hacktivis.me>
+// SPDX-License-Identifier: MIT
+
+unsigned long strtodur(char *s);