Rich Felker | 0b44a03 | 2011-02-12 00:22:29 -0500 | [diff] [blame] | 1 | #include <string.h> |
| 2 | #include <stdlib.h> |
| 3 | #include <stdint.h> |
| 4 | #include <limits.h> |
| 5 | |
| 6 | #define ALIGN (sizeof(size_t)-1) |
| 7 | #define ONES ((size_t)-1/UCHAR_MAX) |
| 8 | #define HIGHS (ONES * (UCHAR_MAX/2+1)) |
| 9 | #define HASZERO(x) ((x)-ONES & ~(x) & HIGHS) |
| 10 | |
| 11 | char *strchr(const char *s, int c) |
| 12 | { |
Rich Felker | c68b263 | 2011-04-03 18:16:11 -0400 | [diff] [blame] | 13 | size_t *w, k; |
| 14 | |
| 15 | c = (unsigned char)c; |
Rich Felker | 0b44a03 | 2011-02-12 00:22:29 -0500 | [diff] [blame] | 16 | if (!c) return (char *)s + strlen(s); |
Rich Felker | c68b263 | 2011-04-03 18:16:11 -0400 | [diff] [blame] | 17 | |
Rich Felker | 16675df | 2011-04-05 09:27:41 -0400 | [diff] [blame] | 18 | for (; ((uintptr_t)s & ALIGN); s++) |
Rich Felker | c68b263 | 2011-04-03 18:16:11 -0400 | [diff] [blame] | 19 | if (*(unsigned char *)s == c) return (char *)s; |
Rich Felker | 16675df | 2011-04-05 09:27:41 -0400 | [diff] [blame] | 20 | else if (!*s) return 0; |
Rich Felker | c68b263 | 2011-04-03 18:16:11 -0400 | [diff] [blame] | 21 | k = ONES * c; |
| 22 | for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++); |
| 23 | for (s = (void *)w; *s; s++) |
| 24 | if (*(unsigned char *)s == c) return (char *)s; |
| 25 | return 0; |
Rich Felker | 0b44a03 | 2011-02-12 00:22:29 -0500 | [diff] [blame] | 26 | } |