Created
August 1, 2022 22:14
-
-
Save skeeto/5cafad10171d6a757d45ef5268f24c43 to your computer and use it in GitHub Desktop.
Finder over a file descriptor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
struct finder { | |
long long lineno; | |
unsigned char *needle; | |
size_t nlen, noff; | |
size_t hlen, hoff; | |
int fd; | |
unsigned char haystack[1<<14]; // may be smaller than the needle | |
}; | |
static void | |
finder_init(struct finder *f, int fd, const void *needle, size_t len) | |
{ | |
f->needle = (unsigned char *)needle; | |
f->nlen = len; | |
f->noff = 0; | |
f->hlen = 0; | |
f->hoff = 0; | |
f->lineno = 0; | |
f->fd = fd; | |
} | |
static unsigned char | |
xlower(unsigned char c) | |
{ | |
return c + ((c >= 'A' && c <= 'Z') << 5); | |
} | |
// Return the line number of the next instance of the needle, zero for | |
// EOF, and -1 on error. | |
static long long | |
finder_next(struct finder *f) | |
{ | |
for (;;) { | |
while (f->hoff < f->hlen) { | |
unsigned char c = xlower(f->haystack[f->hoff++]); | |
if (c == '\n') { | |
int ismatch = f->noff == f->nlen; | |
f->lineno++; | |
f->noff = 0; | |
if (ismatch) { | |
return f->lineno; | |
} | |
} else if (f->noff < f->nlen && c == xlower(f->needle[f->noff])) { | |
f->noff++; | |
} else { | |
f->noff = (size_t)-1; | |
} | |
} | |
int r = read(f->fd, f->haystack, sizeof(f->haystack)); | |
switch (r) { | |
case -1: return -1; | |
case 0: return 0; | |
default: f->hoff = 0; | |
f->hlen = r; | |
} | |
} | |
} | |
int | |
main(int argc, char **argv) | |
{ | |
struct finder f[1]; | |
finder_init(f, 0, argv[argc-1], strlen(argv[argc-1])); | |
for (;;) { | |
long long lineno = finder_next(f); | |
switch (lineno) { | |
case -1: return 1; | |
case 0: fflush(stdout); | |
return ferror(stdout); | |
default: printf("%lld\n", lineno); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment