diff options
author | Leah Neukirchen <leah@vuxu.org> | 2017-08-21 20:17:03 +0200 |
---|---|---|
committer | Leah Neukirchen <leah@vuxu.org> | 2017-08-21 20:17:03 +0200 |
commit | e8269dc42cceedd2e82ebf860b1f3fa8a8b69ded (patch) | |
tree | a9c06a7756f4e22b2bee0f568f6d050c5cdbee6a /holes.c | |
parent | de5d95e0fb849c74e05a865fa2c2e1abf7800cf9 (diff) | |
download | holes-e8269dc42cceedd2e82ebf860b1f3fa8a8b69ded.tar.gz holes-e8269dc42cceedd2e82ebf860b1f3fa8a8b69ded.tar.xz holes-e8269dc42cceedd2e82ebf860b1f3fa8a8b69ded.zip |
holes: don't use bytewise i/o
Use fread to reduce overhead of calling stdio. Then use memchr to find the initial thing we search for (to dismiss nonmatching blocks quickly), then loop manually while it matches.
Diffstat (limited to 'holes.c')
-rw-r--r-- | holes.c | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/holes.c b/holes.c index 41fc50c..6bff701 100644 --- a/holes.c +++ b/holes.c @@ -16,20 +16,37 @@ holes(FILE *input, char *filename) { off_t offset = 0; off_t run = 0; - int ch; + static char buf[16384]; - while ((ch = getc_unlocked(input)) != EOF) { - if (ch == byte) { - run++; + int len; + int i; + char *d; + + while ((len = fread(buf, 1, sizeof buf, input)) >= 1) { + if (run == 0) { + d = memchr(buf, byte, len); + if (!d) { + offset += len; + continue; + } + i = d - buf; + offset += i; } else { - if (run >= minlen) { - if (filename) - printf("%s: ", filename); - printf("%08lx %ld\n", offset - run, run); + i = 0; + } + for (; i < len; i++) { + if (buf[i] == byte) { + run++; + } else { + if (run >= minlen) { + if (filename) + printf("%s: ", filename); + printf("%08lx %ld\n", offset - run, run); + } + run = 0; } - run = 0; + offset++; } - offset++; } if (ferror(input)) { fprintf(stderr, "%s: can't read '%s': %s\n", |