| /* stringlib: replace implementation */ |
| |
| #ifndef STRINGLIB_FASTSEARCH_H |
| #error must include "stringlib/fastsearch.h" before including this module |
| #endif |
| |
| Py_LOCAL_INLINE(void) |
| STRINGLIB(replace_1char_inplace)(STRINGLIB_CHAR* s, STRINGLIB_CHAR* end, |
| Py_UCS4 u1, Py_UCS4 u2, Py_ssize_t maxcount) |
| { |
| *s = u2; |
| while (--maxcount && ++s != end) { |
| /* Find the next character to be replaced. |
| |
| If it occurs often, it is faster to scan for it using an inline |
| loop. If it occurs seldom, it is faster to scan for it using a |
| function call; the overhead of the function call is amortized |
| across the many characters that call covers. We start with an |
| inline loop and use a heuristic to determine whether to fall back |
| to a function call. */ |
| if (*s != u1) { |
| int attempts = 10; |
| /* search u1 in a dummy loop */ |
| while (1) { |
| if (++s == end) |
| return; |
| if (*s == u1) |
| break; |
| if (!--attempts) { |
| /* if u1 was not found for attempts iterations, |
| use FASTSEARCH() or memchr() */ |
| #if STRINGLIB_SIZEOF_CHAR == 1 |
| s++; |
| s = memchr(s, u1, end - s); |
| if (s == NULL) |
| return; |
| #else |
| Py_ssize_t i; |
| STRINGLIB_CHAR ch1 = (STRINGLIB_CHAR) u1; |
| s++; |
| i = FASTSEARCH(s, end - s, &ch1, 1, 0, FAST_SEARCH); |
| if (i < 0) |
| return; |
| s += i; |
| #endif |
| /* restart the dummy loop */ |
| break; |
| } |
| } |
| } |
| *s = u2; |
| } |
| } |