diff options
Diffstat (limited to 'string/strpbrk.c')
-rw-r--r-- | string/strpbrk.c | 120 |
1 files changed, 109 insertions, 11 deletions
diff --git a/string/strpbrk.c b/string/strpbrk.c index 4f1d9b72bb..01cd55afdf 100644 --- a/string/strpbrk.c +++ b/string/strpbrk.c @@ -16,26 +16,124 @@ <http://www.gnu.org/licenses/>. */ #include <string.h> - +#include <stdint.h> #undef strpbrk +#undef strcspn + + +#ifdef AS_STRCSPN +# ifndef STRPBRK +# define STRPBRK strcspn +# endif +# define RETURN_TYPE size_t +# define RETURN(c) return c +#else +# define RETURN_TYPE char * +# define RETURN(c) return (char *) (s[c] != '\0' ? s + c : NULL) +#endif #ifndef STRPBRK #define STRPBRK strpbrk #endif + /* Find the first occurrence in S of any character in ACCEPT. */ -char * -STRPBRK (const char *s, const char *accept) +RETURN_TYPE +STRPBRK (const char *_s, const char *_accept) { - while (*s != '\0') + unsigned char *s = (unsigned char *) _s; + unsigned char *a = (unsigned char *) _accept; + +#ifndef LATE_CHECK + /* We need to align s to 4 bytes. We do check now to avoid expensive table + construction. */ + do + { + if (s[0] == *a) + RETURN(0); + } + while (*a++); + a = (unsigned char *) _accept; + + /* We couldn't do these checks in one loop as gcc + messes up register allocation. */ + do + { + if (s[1] == *a) + RETURN(1); + } + while (*a++); + a = (unsigned char *) _accept; + + do + { + if (s[2] == *a) + RETURN(2); + } + while (*a++); + a = (unsigned char *) _accept; + + do + { + if (s[3] == *a) + RETURN(3); + } + while (*a++); + a = (unsigned char *) _accept; + +#endif + + unsigned char table[256]; + memset (table, 0, 256); + do { - const char *a = accept; - while (*a != '\0') - if (*a++ == *s) - return (char *) s; - ++s; + table[*a] = 1; } + while (*a++); + unsigned char s0, s1, s2, s3; + size_t count = 0; +#ifdef LATE_CHECK + s0 = s[count + 0]; + s1 = s[count + 1]; + s2 = s[count + 2]; + s3 = s[count + 3]; + if (table[s0]) + goto ret0; + if (table[s1]) + goto ret1; + if (table[s2]) + goto ret2; + if (table[s3]) + goto ret3; - return NULL; +#endif + + count = 4 - ((uintptr_t) s) % 4; + + while (1) + { + s0 = s[count + 0]; + s1 = s[count + 1]; + s2 = s[count + 2]; + s3 = s[count + 3]; + if (table[s0]) + goto ret0; + if (table[s1]) + goto ret1; + if (table[s2]) + goto ret2; + if (table[s3]) + goto ret3; + count += 4; + } + ret3: + count++; + ret2: + count++; + ret1: + count++; + ret0: + RETURN(count); } -libc_hidden_builtin_def (strpbrk) + +libc_hidden_builtin_def (STRPBRK) |