aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--match.c36
-rw-r--r--utils.c12
-rw-r--r--utils.h2
3 files changed, 19 insertions, 31 deletions
diff --git a/match.c b/match.c
index c4faeb7..f8205d4 100644
--- a/match.c
+++ b/match.c
@@ -2,6 +2,7 @@
// match.c - Code for the BP virtual machine that performs the matching.
//
+#include <ctype.h>
#include <err.h>
#include <limits.h>
#include <stdbool.h>
@@ -257,22 +258,23 @@ static match_t *_next_match(def_t *defs, cache_t *cache, file_t *f, const char *
pat_t *first = first_pat(defs, pat);
// Performance optimization: if the pattern starts with a string literal,
- // we can just rely on the highly optimized strstr()/strcasestr()
- // implementations to skip past areas where we know we won't find a match.
- if (!skip && first->type == BP_STRING) {
- for (size_t i = 0; i < first->min_matchlen; i++)
- if (first->args.string[i] == '\0')
- goto pattern_search;
- char *tmp = strndup(first->args.string, first->min_matchlen);
- char *found = (ignorecase ? strcasestr : strstr)(str, tmp);
- if (found)
- str = found;
- else
- str += strlen(str); // Use += strlen here instead of f->end to handle files with NULL bytes
- free(tmp);
- }
-
- pattern_search:
+ // we can just rely on the highly optimized memmem() implementation to skip
+ // past areas where we know we won't find a match.
+ if (!skip && first->type == BP_STRING && first->min_matchlen > 0) {
+ if (ignorecase) {
+ char c1 = first->args.string[0];
+ char *upper = memchr(str, toupper(c1), (size_t)(str - f->end));
+ char *lower = isalpha(c1) ? memchr(str, tolower(c1), (size_t)(str - f->end)) : NULL;
+ if (upper && lower)
+ str = upper < lower ? upper : lower;
+ else if (upper) str = upper;
+ else if (lower) str = lower;
+ } else {
+ char *found = memmem(str, (size_t)(str - f->end), first->args.string, first->min_matchlen);
+ str = found ? found : f->end;
+ }
+ }
+
if (str > f->end) return NULL;
do {
@@ -341,7 +343,7 @@ static match_t *match(def_t *defs, cache_t *cache, file_t *f, const char *str, p
}
case BP_STRING: {
if (&str[pat->min_matchlen] > f->end) return NULL;
- if (pat->min_matchlen > 0 && (ignorecase ? memicmp : memcmp)(str, pat->args.string, pat->min_matchlen) != 0)
+ if (pat->min_matchlen > 0 && (ignorecase ? strncasecmp : strncmp)(str, pat->args.string, pat->min_matchlen) != 0)
return NULL;
return new_match(defs, pat, str, str + pat->min_matchlen, NULL);
}
diff --git a/utils.c b/utils.c
index 47958f7..9057df6 100644
--- a/utils.c
+++ b/utils.c
@@ -128,18 +128,6 @@ char unescapechar(const char *escaped, const char **end)
}
//
-// Case-insensitive memory comparison
-//
-int memicmp(const void *v1, const void *v2, size_t n)
-{
- int result = 0;
- const char *s1 = (const char*)v1, *s2 = (const char*)v2;
- while (n-- > 0 && (result = tolower(*(s1++)) - tolower(*(s2++))) == 0)
- ;
- return result;
-}
-
-//
// Free memory, but also set the pointer to NULL for safety
//
void delete(void *p)
diff --git a/utils.h b/utils.h
index 59fedf7..09b0c39 100644
--- a/utils.h
+++ b/utils.h
@@ -58,8 +58,6 @@ bool matchchar(const char **str, char c, bool skip_nl);
__attribute__((nonnull))
bool matchstr(const char **str, const char *target, bool skip_nl);
__attribute__((nonnull))
-int memicmp(const void *s1, const void *s2, size_t n);
-__attribute__((nonnull))
void delete(void *p);
#endif