]> git.scottworley.com Git - uniqt/blame - uniqt.c
Prompt output: Line-buffered
[uniqt] / uniqt.c
CommitLineData
ccaad020 1#define _POSIX_C_SOURCE 200809L
63eb64b5
SW
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <time.h>
7
8void die(const char *message) {
9 fputs(message, stderr);
10 fputc('\n', stderr);
11 exit(1);
12}
13
14void die_err(const char *message) {
15 perror(message);
16 exit(1);
17}
18
19char *encode_time(time_t t) {
20 struct tm tm;
21 localtime_r(&t, &tm);
22 const size_t size = 20;
23 char *out = (char *)malloc(size);
24 if (strftime(out, size, "%Y %m %d %H %M %S", &tm) != size - 1)
25 die("Couldn't format time");
26 return out;
27}
28
29typedef struct {
30 time_t start, end;
31} time_range_t;
32
33const time_t NULL_TIME = (time_t)-1;
34
35static time_range_t make_time_range(time_t t) { return (time_range_t){t, t}; }
36
37static void extend_time_range(time_range_t *r, time_t t) { r->end = t; }
38
39static char *read_line() {
40 char *line = NULL;
41 int scanf_ret = scanf("%m[^\n]", &line);
42 if (scanf_ret == EOF && ferror(stdin))
43 die_err("Error reading");
44 int newline = getchar();
45 if (newline != EOF && newline != (int)'\n')
46 die("Expected newline");
ccaad020
SW
47 if (scanf_ret == 0 && newline == (int)'\n')
48 return strdup("\n");
63eb64b5
SW
49 return line;
50}
51
52static void write_line(time_range_t *range, char *line) {
53 if (line == NULL)
54 return;
55 if (printf("%ld %ld %s\n", range->start, range->end, line) < 0)
56 die("Couldn't write");
be6fd520
SW
57 if (fflush(stdout) == EOF)
58 die_err("Couldn't flush");
63eb64b5
SW
59}
60
61static int same(char *a, char *b) { return a && b && strcmp(a, b) == 0; }
62
63static void uniqt() {
64 char *current_line = NULL;
65 time_range_t current_time_range = make_time_range(NULL_TIME);
66 for (;;) {
67 char *new_line = read_line();
68 if (new_line == NULL)
69 break;
70 time_t now = time(NULL);
71 if (same(current_line, new_line)) {
72 free(new_line);
73 extend_time_range(&current_time_range, now);
74 } else {
75 write_line(&current_time_range, current_line);
76 free(current_line);
77 current_line = new_line;
78 current_time_range = make_time_range(now);
79 }
80 }
81 write_line(&current_time_range, current_line);
82 free(current_line);
83}
84
85int main() {
86 uniqt();
87 return 0;
88}