summaryrefslogtreecommitdiff
path: root/src/binsearch.c
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2018-10-21 19:48:24 +0300
committerJari Vetoniemi <mailroxas@gmail.com>2018-10-21 19:48:24 +0300
commit840d92358e311b405475ba7488ec55cc3f4f5fae (patch)
treece7246e8dede9372860b49daf47c6fa7abd0566c /src/binsearch.c
parentf168742fd9c0453ba7270c365838da1d75eeb6c0 (diff)
Give binsearch ability to find all matches
Diffstat (limited to 'src/binsearch.c')
-rw-r--r--src/binsearch.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/src/binsearch.c b/src/binsearch.c
index a4195ba..d382c5a 100644
--- a/src/binsearch.c
+++ b/src/binsearch.c
@@ -2,12 +2,16 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include <util.h>
#include <err.h>
+static bool FOUND = false;
+
static void
usage(const char *argv0)
{
- fprintf(stderr, "usage: %s needle [window-size] < haystack\n", argv0);
+ fprintf(stderr, "usage: %s needle first [window-size] < haystack\n"
+ " %s needle all [window-size] < haystack\n", argv0, argv0);
exit(EXIT_FAILURE);
}
@@ -23,14 +27,17 @@ search(const char *haystack, const char *needle, const size_t window_size)
}
static void
-search_and_exit_if_match(const char *haystack, const char *needle, const size_t window_size, const size_t offset)
+search_and_print_if_match(const char *haystack, const char *needle, const size_t window_size, const size_t offset, const bool exit_on_match)
{
const char *match;
if ((match = search(haystack, needle, window_size))) {
+ FOUND = true;
printf("%zu\n", offset + match - haystack);
- free((void*)needle);
- free((void*)haystack);
- exit(EXIT_SUCCESS);
+ if (exit_on_match) {
+ free((void*)needle);
+ free((void*)haystack);
+ exit(EXIT_SUCCESS);
+ }
}
}
@@ -41,10 +48,23 @@ main(int argc, const char *argv[])
size_t window_size = 4096 * 1024;
bool has_window_size = false;
- if (argc < 2)
+ if (argc < 3)
usage(argv[0]);
- else if (argc > 2) {
- window_size = strtoull(argv[2], NULL, 10);
+
+ enum {
+ FIRST,
+ ALL
+ } mode;
+
+ if (!strcmp(argv[2], "first"))
+ mode = FIRST;
+ else if (!strcmp(argv[2], "all"))
+ mode = ALL;
+ else
+ errx(EXIT_FAILURE, "mode must be first or all");
+
+ if (argc > 3) {
+ window_size = hexdecstrtoull(argv[3], NULL);
has_window_size = true;
}
@@ -55,7 +75,12 @@ main(int argc, const char *argv[])
if (!has_window_size) {
fseek(f, 0, SEEK_END);
const long tell = ftell(f);
- window_size = (tell > 0 ? (size_t)tell : window_size);
+
+ if (tell < 0)
+ warnx("can't figure out the size of a needle, not a normal file? fallbacking to a window size of %zu bytes", window_size);
+ else
+ window_size = tell;
+
fseek(f, 0, SEEK_SET);
}
@@ -71,14 +96,14 @@ main(int argc, const char *argv[])
err(EXIT_FAILURE, "calloc");
size_t rd = 0, offset = 0;
- while ((rd = fread(haystack + window_size * !!offset, 1 + !offset, window_size, stdin))) {
- search_and_exit_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset);
+ while ((rd = fread(haystack + window_size * !!offset, 1, window_size * (1 + !offset), stdin))) {
+ search_and_print_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset, (mode == FIRST));
offset += window_size;
memmove(haystack, haystack + window_size, window_size);
}
- search_and_exit_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset);
+ search_and_print_if_match(haystack, needle, (rd >= window_size ? window_size : 0), offset, (mode == FIRST));
free(needle);
free(haystack);
- return EXIT_FAILURE;
+ return (FOUND ? EXIT_SUCCESS : EXIT_FAILURE);
}