From: Scott Worley Date: Fri, 15 Sep 2023 00:52:51 +0000 (-0700) Subject: Begin X-Git-Tag: v1.0.0~6 X-Git-Url: http://git.scottworley.com/uniqt/commitdiff_plain/63eb64b5b01920499f9ea1a1d16a59eda6f716e3?ds=inline Begin --- 63eb64b5b01920499f9ea1a1d16a59eda6f716e3 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a18dfa6 --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +prefix = /usr/local +bindir = $(prefix)/bin +INSTALL = install + +uniqt: + +%: %.c + $(CC) -Wall -Wextra -std=c99 -o $@ $^ + +.PHONY: install +install: uniqt + $(INSTALL) -d $(DESTDIR)$(bindir) + $(INSTALL) -m 755 $^ $(DESTDIR)$(bindir) + +.PHONY: clean +clean: + -rm uniqt diff --git a/uniqt.c b/uniqt.c new file mode 100644 index 0000000..2b7d229 --- /dev/null +++ b/uniqt.c @@ -0,0 +1,84 @@ +#define _POSIX_C_SOURCE 199309L + +#include +#include +#include +#include + +void die(const char *message) { + fputs(message, stderr); + fputc('\n', stderr); + exit(1); +} + +void die_err(const char *message) { + perror(message); + exit(1); +} + +char *encode_time(time_t t) { + struct tm tm; + localtime_r(&t, &tm); + const size_t size = 20; + char *out = (char *)malloc(size); + if (strftime(out, size, "%Y %m %d %H %M %S", &tm) != size - 1) + die("Couldn't format time"); + return out; +} + +typedef struct { + time_t start, end; +} time_range_t; + +const time_t NULL_TIME = (time_t)-1; + +static time_range_t make_time_range(time_t t) { return (time_range_t){t, t}; } + +static void extend_time_range(time_range_t *r, time_t t) { r->end = t; } + +static char *read_line() { + char *line = NULL; + int scanf_ret = scanf("%m[^\n]", &line); + if (scanf_ret == EOF && ferror(stdin)) + die_err("Error reading"); + int newline = getchar(); + if (newline != EOF && newline != (int)'\n') + die("Expected newline"); + return line; +} + +static void write_line(time_range_t *range, char *line) { + if (line == NULL) + return; + if (printf("%ld %ld %s\n", range->start, range->end, line) < 0) + die("Couldn't write"); +} + +static int same(char *a, char *b) { return a && b && strcmp(a, b) == 0; } + +static void uniqt() { + char *current_line = NULL; + time_range_t current_time_range = make_time_range(NULL_TIME); + for (;;) { + char *new_line = read_line(); + if (new_line == NULL) + break; + time_t now = time(NULL); + if (same(current_line, new_line)) { + free(new_line); + extend_time_range(¤t_time_range, now); + } else { + write_line(¤t_time_range, current_line); + free(current_line); + current_line = new_line; + current_time_range = make_time_range(now); + } + } + write_line(¤t_time_range, current_line); + free(current_line); +} + +int main() { + uniqt(); + return 0; +}