/* SPDX-License-Identifier: Apache-2.0 */ /* Copyright 2025 Thorsten Töpper * * I noticed GNU uniq -u not always removed all overlaps, instead * of spending hours in creating a reproducable test case and code * review, a simple custom implementation of that mode. * * vim:ts=4:sw=4:expandtab */ #include #include #include #include #include #include #include #include "trace_macros.h" #define LINE_LENGTH 4096 /* prev=(cur)?0:1; less cycles? */ #define INDEXSWITCH cur=(cur+1)%2; prev=(prev+1)%2; int main(int argc, char **argv) { FILE *fdin = stdin; char *lines[2]; int cur = 1, prev = 0; bool duplicate = false; if (argc > 1) { if (strncmp(argv[1], "-", 2) != 0) { if ((fdin=fopen(argv[1], "r")) == NULL) { LOGERR("ERROR: Failed to open file %s: %s\n", argv[1], strerror(errno)); return EXIT_FAILURE; } } } lines[0] = calloc(LINE_LENGTH, sizeof(char)); lines[1] = calloc(LINE_LENGTH, sizeof(char)); if (lines[0] == NULL || lines[1] == NULL) { LOGERR("ERROR: Failed to allocate 8kiB...\n"); return EXIT_FAILURE; } /* preparation */ if (fgets(lines[prev], LINE_LENGTH, fdin) == NULL) { LOGERR("ERROR: Failed to read input line.\n"); return EXIT_FAILURE; } /* parsing input */ while (fgets(lines[cur], LINE_LENGTH, fdin) != NULL) { if (strcmp(lines[cur], lines[prev]) == 0) { duplicate = true; continue; } if ( ! duplicate ) { fputs(lines[prev], stdout); } else { duplicate = false; } INDEXSWITCH; } /* last line */ if ( ! duplicate ) { fputs(lines[prev], stdout); } if (fdin != stdin) fclose(fdin); return EXIT_SUCCESS; }