DF-5706 / memcchr_fixed.c
/* rig file: fix.diff applied to the pristine body */ #include "prelude.h" #if LONG_BIT != 32 && LONG_BIT != 64 #error Unsupported word size #endif #define LONGPTR_MASK (sizeof(long) - 1) #define TESTBYTE \ do { \ if (*p != (unsigned char)c) \ goto done; \ p++; \ } while (0) void * memcchr(const void *begin, int c, size_t n) { const unsigned long *lp; const unsigned char *p, *end; unsigned long word; /* Four or eight repetitions of `c'. */ word = (unsigned char)c; word |= word << 8; word |= word << 16; #if LONG_BIT >= 64 word |= word << 32; #endif /* Don't perform memory I/O when passing a zero-length buffer. */ if (n == 0) return (NULL); end = (const unsigned char *)begin + n; /* Compare bytewise until word aligned: no loads below begin. */ for (p = begin; p < end && ((uintptr_t)p & LONGPTR_MASK);) TESTBYTE; /* Compare one word at a time while the whole word is in range. */ for (lp = (const unsigned long *)p; (const unsigned char *)(lp + 1) <= end; lp++) { if (*lp != word) { p = (const unsigned char *)lp; TESTBYTE; TESTBYTE; TESTBYTE; #if LONG_BIT >= 64 TESTBYTE; TESTBYTE; TESTBYTE; TESTBYTE; #endif goto done; } } /* Trailing bytes: no loads past end. */ for (p = (const unsigned char *)lp; p < end;) TESTBYTE; return (NULL); done: /* * If the end of the buffer is not word aligned, the previous * loops may obtain an address that's beyond the end of the * buffer. */ if (p < end) return (__DECONST(void *, p)); return (NULL); } |