sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit 0dc0d3ded5f051a0840d9ebc2d03226dd97b364b
parent b56117e67e50fafdc18cb2c8f4100594e51c5b45
Author: FRIGN <dev@frign.de>
Date:   Thu Mar 10 07:02:04 +0100

Support NUL containing lines in uniq(1)

Diffstat:
README | 2+-
uniq.c | 72++++++++++++++++++++++++++++++++++++++----------------------------------
2 files changed, 39 insertions(+), 35 deletions(-)
diff --git a/README b/README @@ -97,7 +97,7 @@ The following tools are implemented: 0=*|o tty . 0=*|o uname . 0#*|o unexpand . - =*|o uniq . +0=*|o uniq . 0=*|o unlink . 0=*|o uudecode . 0=*|o uuencode . diff --git a/uniq.c b/uniq.c @@ -4,6 +4,7 @@ #include <stdlib.h> #include <string.h> +#include "text.h" #include "util.h" static const char *countfmt = ""; @@ -12,59 +13,60 @@ static int uflag = 0; static int fskip = 0; static int sskip = 0; -static char *prevline = NULL; -static char *prevoffset = NULL; +static struct line prevl; +static ssize_t prevoff = -1; static long prevlinecount = 0; -static size_t prevlinesiz = 0; -static const char * -uniqskip(const char *l) +static size_t +uniqskip(struct line *l) { - const char *lo = l; + size_t i; int f = fskip, s = sskip; - for (; f; --f) { - while (isblank(*lo)) - lo++; - while (*lo && !isblank(*lo)) - lo++; + for (i = 0; i < l->len && f; --f) { + while (isblank(l->data[i])) + i++; + while (i < l->len && !isblank(l->data[i])) + i++; } - for (; s && *lo && *lo != '\n'; --s, ++lo); + for (; s && i < l->len && l->data[i] != '\n'; --s, i++) + ; - return lo; + return i; } static void -uniqline(FILE *ofp, const char *l, size_t len) +uniqline(FILE *ofp, struct line *l) { - const char *loffset = l ? uniqskip(l) : l; + size_t loff; - int linesequel = l && prevoffset && - !strcmp(loffset, prevoffset); + if (l) { + loff = uniqskip(l); - if (linesequel) { - ++prevlinecount; - return; + if (prevoff >= 0 && (l->len - loff) == (prevl.len - prevoff) && + !memcmp(l->data + loff, prevl.data + prevoff, l->len - loff)) { + ++prevlinecount; + return; + } } - if (prevoffset) { + if (prevoff >= 0) { if ((prevlinecount == 1 && !dflag) || (prevlinecount != 1 && !uflag)) { if (*countfmt) fprintf(ofp, countfmt, prevlinecount); - fputs(prevline, ofp); + fwrite(prevl.data, 1, prevl.len, ofp); } - prevoffset = NULL; + prevoff = -1; } if (l) { - if (!prevline || len >= prevlinesiz) { - prevlinesiz = len + 1; - prevline = erealloc(prevline, prevlinesiz); + if (!prevl.data || l->len >= prevl.len) { + prevl.len = l->len; + prevl.data = erealloc(prevl.data, prevl.len); } - memcpy(prevline, l, len); - prevline[len] = '\0'; - prevoffset = prevline + (loffset - l); + memcpy(prevl.data, l->data, prevl.len); + prevoff = loff; } prevlinecount = 1; } @@ -72,18 +74,20 @@ uniqline(FILE *ofp, const char *l, size_t len) static void uniq(FILE *fp, FILE *ofp) { - char *buf = NULL; - size_t size = 0; + static struct line line; + static size_t size; ssize_t len; - while ((len = getline(&buf, &size, fp)) > 0) - uniqline(ofp, buf, (size_t)len); + while ((len = getline(&line.data, &size, fp)) > 0) { + line.len = len; + uniqline(ofp, &line); + } } static void uniqfinish(FILE *ofp) { - uniqline(ofp, NULL, 0); + uniqline(ofp, NULL); } static void