#include #include #include #define aliases __attribute__((__may_alias__)) #define byte_repeat(x) ((size_t)~0 / 0xff * (x)) #define word_has_zero(x) (((x) - byte_repeat(0x01)) & ~(x) & byte_repeat(0x80)) #define word_tag_range(x, t, s, e) ((((x) | byte_repeat(t)) \ - byte_repeat(s) & ~((x) | byte_repeat(t)) - \ byte_repeat((e) + 1)) & (~(x) & byte_repeat(t))) #define word_to_tolower(x) ((x) - (word_tag_range((x), 'a', 'z', 0x80)) >> 2) #define weak_alias(o, n) extern __typeof__(o) n __attribute__((weak, alias(#o))) int strncasecmp(const char *_l, const char *_r, size_t n) { const unsigned char *l = (const void *)_l, *r = (const void *)_r; const size_t aliases *wl, aliases *wr; if (!n--) return 0; if (n < sizeof(size_t) * 3 || ((uintptr_t)l | (uintptr_t)r) & sizeof(size_t) - 1) goto bytewise; for (;(uintptr_t)l & sizeof(size_t) - 1 && *l && tolower(*l) == tolower(*r); l++, r++, n--); if ((uintptr_t)l & sizeof(size_t) - 1) return tolower(*l) - tolower(*r); wl = (const void *)l; wr = (const void *)r; for (; n >= sizeof(size_t) && !word_has_zero(*wl) && word_to_tolower(*wl) == word_to_tolower(*wr) ; wl++, wr++, n -= sizeof(size_t)); l = (const void *)wl; r = (const void *)wr; bytewise: for (; n && *l && tolower(*l) == tolower(*r); l++, r++, n--); return tolower(*l) - tolower(*r); } int __strncasecmp_l(const char *l, const char *r, size_t n, locale_t unused) { return strncasecmp(l, r, n); } weak_alias(__strncasecmp_l, strncasecmp_l);