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 | |
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.
-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", |