From 840d92358e311b405475ba7488ec55cc3f4f5fae Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Sun, 21 Oct 2018 19:48:24 +0300 Subject: Give binsearch ability to find all matches --- src/binsearch.c | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'src/binsearch.c') 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 #include #include +#include #include +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); } -- cgit v1.2.3