mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
string.c (mrb_memsearch_ss): faster integer-wise substring search
The function is based on @WojciechMula's code from the repository https://github.com/WojciechMula/sse4-strstr.git Since it's licensed under 2 clause BSD, we updated LEGAL file too.
This commit is contained in:
@@ -4,10 +4,41 @@ LEGAL NOTICE INFORMATION
|
||||
All the files in this distribution are covered under the MIT license
|
||||
(see the file LICENSE) except some files mentioned below:
|
||||
|
||||
- src/string.c: mrb_memsearch_ss() is based on 2 clause BSD license code by Wojciech Muła (@WojciechMula)
|
||||
- src/readfloat.c: public domain by Yasuhiro Matsumoto (@mattn)
|
||||
- src/fmt_fp.c: public domain by Dave Hylands (@dhylands)
|
||||
- mrbgems/mruby-dir/src/Win/dirent.c: MIT-like license by Kevlin Henney
|
||||
|
||||
[src/string.c]
|
||||
The implementation of mrb_memsearch_ss() is taken from
|
||||
https://github.com/WojciechMula/sse4-strstr.git
|
||||
|
||||
Copyright (c) 2008-2016, Wojciech Muła
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
[src/readfloat.c]
|
||||
|
||||
strtod implementation.
|
||||
|
||||
+76
-9
@@ -263,6 +263,15 @@ mrb_gc_free_str(mrb_state *mrb, struct RString *str)
|
||||
mrb_free(mrb, str->as.heap.ptr);
|
||||
}
|
||||
|
||||
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
|
||||
defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
|
||||
defined(__mc68020__)
|
||||
# define ALIGNED_WORD_ACCESS 0
|
||||
#else
|
||||
# define ALIGNED_WORD_ACCESS 1
|
||||
#endif
|
||||
|
||||
#ifdef MRB_UTF8_STRING
|
||||
|
||||
#define NOASCII(c) ((c) & 0x80)
|
||||
@@ -327,15 +336,6 @@ search_nonascii(const char *p, const char *e)
|
||||
# define NONASCII_MASK 0x80808080UL
|
||||
#endif
|
||||
|
||||
#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
|
||||
defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
|
||||
defined(__mc68020__)
|
||||
# define ALIGNED_WORD_ACCESS 0
|
||||
#else
|
||||
# define ALIGNED_WORD_ACCESS 1
|
||||
#endif
|
||||
|
||||
static const char*
|
||||
search_nonascii(const char *p, const char *e)
|
||||
{
|
||||
@@ -564,6 +564,70 @@ 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
|
||||
|
||||
/* The function is taken from https://github.com/WojciechMula/sse4-strstr.git */
|
||||
/* The original source code is under 2 clause BSD license; see LEGAL file. */
|
||||
/* The modifications:
|
||||
|
||||
* port from C++ to C
|
||||
* takes unsigned char*
|
||||
* returns mrb_int
|
||||
* alignment adjustment added
|
||||
*/
|
||||
static inline mrb_int
|
||||
mrb_memsearch_ss(const unsigned char *xs, long m, const unsigned char *ys, long n)
|
||||
{
|
||||
/* maximum pattern length */
|
||||
#define MAX_PATLEN 100
|
||||
|
||||
#ifdef MRB_64BIT
|
||||
#define bitint uint64_t
|
||||
#define MASK1 0x0101010101010101llu
|
||||
#define MASK2 0x7f7f7f7f7f7f7f7fllu
|
||||
#define MASK3 0x8080808080808080llu
|
||||
#else
|
||||
#define bitint uint32_t
|
||||
#define MASK1 0x01010101lu
|
||||
#define MASK2 0x7f7f7f7flu
|
||||
#define MASK3 0x80808080lu
|
||||
#endif
|
||||
|
||||
#if ALIGNED_WORD_ACCESS
|
||||
if ((uintptr_t)ys % sizeof(bitint)) {
|
||||
int l = sizeof(bitint) - (bitint)ys % sizeof(bitint);
|
||||
const unsigned char *p = (unsigned char*)memchr(ys, *xs, l);
|
||||
if (p && (p - ys) < m) {
|
||||
if (memcmp(p, xs, m) == 0) return (mrb_int)(p - ys);
|
||||
ys = p;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const bitint first = MASK1 * (uint8_t)xs[0];
|
||||
const bitint last = MASK1 * (uint8_t)xs[m-1];
|
||||
|
||||
bitint *s0 = (bitint*)(ys);
|
||||
bitint *s1 = (bitint*)(ys+m-1);
|
||||
|
||||
for (mrb_int i=0; i < n; i+=sizeof(bitint), s0++, s1++) {
|
||||
const bitint eq = (*s0 ^ first) | (*s1 ^ last);
|
||||
bitint zeros = ((~eq & MASK2) + MASK1) & (~eq & MASK3);
|
||||
size_t j = 0;
|
||||
|
||||
while (zeros) {
|
||||
if (zeros & 0x80) {
|
||||
const char* substr = (char*)s0 + j + 1;
|
||||
if (memcmp(substr, xs + 1, m - 2) == 0) {
|
||||
return i + j;
|
||||
}
|
||||
}
|
||||
|
||||
zeros >>= 8;
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline mrb_int
|
||||
mrb_memsearch_qs(const unsigned char *xs, mrb_int m, const unsigned char *ys, mrb_int n)
|
||||
{
|
||||
@@ -625,6 +689,9 @@ mrb_memsearch(const char *x0, mrb_int m, const char *y0, mrb_int n)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (m <= MAX_PATLEN) {
|
||||
return mrb_memsearch_ss((const unsigned char*)x0, m, (const unsigned char*)y0, n);
|
||||
}
|
||||
return mrb_memsearch_qs((const unsigned char*)x0, m, (const unsigned char*)y0, n);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user