Re: [PATCH 3/4] diffcore-pickaxe: further refactor count_match()
From: René Scharfe <hidden>
Date: 2016-06-15 22:46:18
Subsystem:
the rest · Maintainer:
Linus Torvalds
Junio C Hamano schrieb:
-static unsigned int count_match(int one_or_more,
- struct diff_filespec *one,
- const char *needle, unsigned long len,
- regex_t *regexp)
+static unsigned int count_match_internal(int one_or_more,
+ const char *data, unsigned long sz,
+ const char *needle, unsigned long len,
+ regex_t *regexp)
{I don't especially like flags like one_or_more. Having two functions (which possibly call a common function that does most of the work) is nicer. And it's a bit sad here because there already are two functions with nice names: count_match() and has_match(). But, well, since the functions are not exported anyway it doesn't matter much.
quoted hunk ↗ jump to hunk
@@ -29,16 +20,14 @@ static unsigned int count_match(int one_or_more, while (*data && !regexec(regexp, data, 1, ®match, flags)) { flags |= REG_NOTBOL; data += regmatch.rm_so; - if (*data) data++; + if (*data) + data++; cnt++; if (one_or_more) break; } - - } else { /* Classic exact string match */ - /* Yes, I've heard of strstr(), but the thing is *data may - * not be NUL terminated. Sue me. - */ + } else { + /* data many not be NUL terminated; we cannot use strstr() */
That looks fishy to me. regexec() expects data to be a NUL-terminated string, so either the comment is wrong or the regexp case needs to take better care to add a NUL at the end of the buffer. In any case, there is also memmem(), which uses the same fast algorithm as strstr() in recent glibc versions. Like this?
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index f4870b4..4c19967 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c@@ -11,7 +11,6 @@ static unsigned int count_match_internal(int one_or_more, regex_t *regexp) { unsigned int cnt = 0; - unsigned long offset; if (regexp) { regmatch_t regmatch;
@@ -27,15 +26,15 @@ static unsigned int count_match_internal(int one_or_more, break; } } else { - /* data many not be NUL terminated; we cannot use strstr() */ - for (offset = 0; offset + len <= sz; offset++) { - /* we count non-overlapping occurrences of needle */ - if (!memcmp(needle, data + offset, len)) { - offset += len - 1; - cnt++; - if (one_or_more) - break; - } + while (sz) { + const char *found = memmem(data, sz, needle, len); + if (!found) + break; + sz -= found - data + len; + data = found + len; + cnt++; + if (one_or_more) + break; } } return cnt;