Serhiy Storchaka | e2cef88 | 2013-04-13 22:45:04 +0300 | [diff] [blame] | 1 | /* stringlib: replace implementation */ |
| 2 | |
| 3 | #ifndef STRINGLIB_FASTSEARCH_H |
| 4 | #error must include "stringlib/fastsearch.h" before including this module |
| 5 | #endif |
| 6 | |
| 7 | Py_LOCAL_INLINE(void) |
| 8 | STRINGLIB(replace_1char_inplace)(STRINGLIB_CHAR* s, STRINGLIB_CHAR* end, |
| 9 | Py_UCS4 u1, Py_UCS4 u2, Py_ssize_t maxcount) |
| 10 | { |
| 11 | *s = u2; |
| 12 | while (--maxcount && ++s != end) { |
| 13 | /* Find the next character to be replaced. |
| 14 | |
| 15 | If it occurs often, it is faster to scan for it using an inline |
| 16 | loop. If it occurs seldom, it is faster to scan for it using a |
| 17 | function call; the overhead of the function call is amortized |
| 18 | across the many characters that call covers. We start with an |
| 19 | inline loop and use a heuristic to determine whether to fall back |
| 20 | to a function call. */ |
| 21 | if (*s != u1) { |
| 22 | int attempts = 10; |
| 23 | /* search u1 in a dummy loop */ |
| 24 | while (1) { |
| 25 | if (++s == end) |
| 26 | return; |
| 27 | if (*s == u1) |
| 28 | break; |
| 29 | if (!--attempts) { |
| 30 | /* if u1 was not found for attempts iterations, |
| 31 | use FASTSEARCH() or memchr() */ |
| 32 | #if STRINGLIB_SIZEOF_CHAR == 1 |
| 33 | s++; |
| 34 | s = memchr(s, u1, end - s); |
| 35 | if (s == NULL) |
| 36 | return; |
| 37 | #else |
| 38 | Py_ssize_t i; |
| 39 | STRINGLIB_CHAR ch1 = (STRINGLIB_CHAR) u1; |
| 40 | s++; |
| 41 | i = FASTSEARCH(s, end - s, &ch1, 1, 0, FAST_SEARCH); |
| 42 | if (i < 0) |
| 43 | return; |
| 44 | s += i; |
| 45 | #endif |
| 46 | /* restart the dummy loop */ |
| 47 | break; |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | *s = u2; |
| 52 | } |
| 53 | } |