about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2017-08-21 20:17:03 +0200
committerLeah Neukirchen <leah@vuxu.org>2017-08-21 20:17:03 +0200
commite8269dc42cceedd2e82ebf860b1f3fa8a8b69ded (patch)
treea9c06a7756f4e22b2bee0f568f6d050c5cdbee6a
parentde5d95e0fb849c74e05a865fa2c2e1abf7800cf9 (diff)
downloadholes-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.c37
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",