1#include <string.h>
2
3#include <limits.h>
4#include <zircon/compiler.h>
5#include <stdint.h>
6
7#define SS (sizeof(size_t))
8#define ALIGN (sizeof(size_t) - 1)
9#define ONES ((size_t)-1 / UCHAR_MAX)
10#define HIGHS (ONES * (UCHAR_MAX / 2 + 1))
11#define HASZERO(x) (((x)-ONES) & ~(x)&HIGHS)
12
13void* memchr(const void* src, int c, size_t n) {
14    const unsigned char* s = src;
15    c = (unsigned char)c;
16    for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--)
17        ;
18    if (n && *s != c) {
19        const size_t* w = (const void*)s;
20#if !__has_feature(address_sanitizer)
21        // This reads past the end of the string, which is usually OK since
22        // it won't cross a page boundary.  But under ASan, even one byte
23        // past the actual end is diagnosed.
24        size_t k = ONES * c;
25        while (n >= SS && !HASZERO(*w ^ k)) {
26            ++w;
27            n -= SS;
28        }
29#endif
30        for (s = (const void*)w; n && *s != c; s++, n--)
31            ;
32    }
33    return n ? (void*)s : 0;
34}
35