summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-02-03 12:07:54 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-02-03 12:59:29 +0900
commit6d9109bf70e2a86537ac3e1f1ea6053aab96132b (patch)
tree82b6267bf7eb598ca6f3ef4ca88ca446d850e846 /src
parent3c67d9b1c0e4970db1d88fccdf7f26c781aa2c5f (diff)
downloadmruby-6d9109bf70e2a86537ac3e1f1ea6053aab96132b.tar.gz
mruby-6d9109bf70e2a86537ac3e1f1ea6053aab96132b.zip
Use simple search for short strings in `mrb_memsearch_qs`; close #4940
Differences from the PR #4940: * Use simple search for short strings only. * "short" means `m+n` is shorter than `MRB_QS_SHORT_STRING_LENGTH`. * The current default value for `MRB_QS_SHORT_STRING_LENGTH` is 2048.
Diffstat (limited to 'src')
-rw-r--r--src/string.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/src/string.c b/src/string.c
index c7b9db17a..e6c23618a 100644
--- a/src/string.c
+++ b/src/string.c
@@ -504,25 +504,45 @@ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
#define str_index_str_by_char(mrb, str, sub, pos) str_index_str(mrb, str, sub, pos)
#endif
+#ifndef MRB_QS_SHORT_STRING_LENGTH
+#define MRB_QS_SHORT_STRING_LENGTH 2048
+#endif
+
static inline mrb_int
mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
{
- const unsigned char *x = xs, *xe = xs + m;
- const unsigned char *y = ys;
- int i;
- ptrdiff_t qstable[256];
+ if (n + m < MRB_QS_SHORT_STRING_LENGTH) {
+ const unsigned char *y = ys;
+ const unsigned char *ye = ys+n-m+1;
- /* Preprocessing */
- for (i = 0; i < 256; ++i)
- qstable[i] = m + 1;
- for (; x < xe; ++x)
- qstable[*x] = xe - x;
- /* Searching */
- for (; y + m <= ys + n; y += *(qstable + y[m])) {
- if (*xs == *y && memcmp(xs, y, m) == 0)
- return (mrb_int)(y - ys);
+ for (;;) {
+ y = memchr(y, xs[0], (size_t)(ye-y));
+ if (y == NULL) return -1;
+ if (memcmp(xs, y, m) == 0) {
+ return (mrb_int)(y - ys);
+ }
+ y++;
+ }
+ return -1;
+ }
+ else {
+ const unsigned char *x = xs, *xe = xs + m;
+ const unsigned char *y = ys;
+ int i;
+ ptrdiff_t qstable[256];
+
+ /* Preprocessing */
+ for (i = 0; i < 256; ++i)
+ qstable[i] = m + 1;
+ for (; x < xe; ++x)
+ qstable[*x] = xe - x;
+ /* Searching */
+ for (; y + m <= ys + n; y += *(qstable + y[m])) {
+ if (*xs == *y && memcmp(xs, y, m) == 0)
+ return (mrb_int)(y - ys);
+ }
+ return -1;
}
- return -1;
}
static mrb_int