diff -r adcd9131b7c6 Objects/stringlib/fastsearch.h --- a/Objects/stringlib/fastsearch.h Fri Dec 09 00:41:46 2016 +0100 +++ b/Objects/stringlib/fastsearch.h Fri Dec 09 18:03:35 2016 +0800 @@ -127,6 +127,65 @@ } Py_LOCAL_INLINE(Py_ssize_t) +STRINGLIB(count_char)(const STRINGLIB_CHAR* s, Py_ssize_t n, + STRINGLIB_CHAR ch, Py_ssize_t maxcount) +{ + Py_ssize_t count = 0; +#if STRINGLIB_SIZEOF_CHAR == 1 +# if SIZEOF_LONG == 4 +# define FAST_COUNT_MASK 0x01010101ul +# elif SIZEOF_LONG == 8 +# define FAST_COUNT_MASK 0x0101010101010101ul +# else +# error C 'long' size should be either 4 or 8! +# endif + const STRINGLIB_CHAR *q = (const STRINGLIB_CHAR *)s; + const STRINGLIB_CHAR *e = (const STRINGLIB_CHAR *)s + n; + const STRINGLIB_CHAR *aligned_end = + (const STRINGLIB_CHAR *) _Py_ALIGN_DOWN(e, SIZEOF_LONG); + while (q < e) { + if (_Py_IS_ALIGNED(q, SIZEOF_LONG)) { + const STRINGLIB_CHAR *_q = q; + while (_q < aligned_end) { + unsigned long block = *(unsigned long *)_q; + /* If any byte equals to ch, then it's zero. */ + unsigned long tmp = block ^ (FAST_COUNT_MASK * ch); + /* Count how many zero bytes in a long. */ + count += + /* highest bits set only if byte is 0x0 or 0x80 */ + ((FAST_COUNT_MASK * 0x80 - ((tmp) & FAST_COUNT_MASK * 0x7f)) & + /* highest bits set only if byte in [0x0, 0x80) */ + (~tmp & (FAST_COUNT_MASK * 0x80))) / 0x80 % 0xff; + /* assume not possible to overflow */ + if (count >= maxcount) + return maxcount; + _q += SIZEOF_LONG; + } + q = _q; + if (q >= e) + break; + } + if (*q++ == ch) { + count++; + if (count == maxcount) + return maxcount; + } + } +# undef FAST_COUNT_MASK +#else + int i; + for (i = 0; i < n; i++) { + if (s[i] == ch) { + count++; + if (count == maxcount) + return maxcount; + } + } +#endif + return count; +} + +Py_LOCAL_INLINE(Py_ssize_t) FASTSEARCH(const STRINGLIB_CHAR* s, Py_ssize_t n, const STRINGLIB_CHAR* p, Py_ssize_t m, Py_ssize_t maxcount, int mode) @@ -150,15 +209,8 @@ else if (mode == FAST_RSEARCH) return STRINGLIB(rfind_char)(s, n, p[0]); else { /* FAST_COUNT */ - for (i = 0; i < n; i++) - if (s[i] == p[0]) { - count++; - if (count == maxcount) - return maxcount; - } - return count; + return STRINGLIB(count_char)(s, n, p[0], maxcount); } - return -1; } mlast = m - 1;