/* Detect whether the character used to fill mask is in X */ #define DETECTCHAR(X,MASK) (DETECTNULL(X^MASK)) #endif /* OPTIMIZED_FOR_SIZE */ static char * strchr (const char *s, int c) { char pc = (char) c; #ifndef OPTIMIZED_FOR_SIZE unsigned long *ps, mask = 0; size_t i; /* If s is unaligned, punt into the byte search loop. This should be rare. */ if (!UNALIGNED (s)) { ps = (unsigned long *) s; for (i = 0; i < sizeof (unsigned long); i++) mask = ((mask << CHAR_BIT) + ((unsigned char) pc & ~(~0 << CHAR_BIT))); /* Move ps a block at a time. */ while (!DETECTNULL (*ps) && !DETECTCHAR (*ps, mask)) ps++; /* Pick up any residual with a byte searcher. */ s = (char *) ps; } #endif /* The normal byte-search loop. */ while (*s && *s != pc) s++; return *s == pc ? (char *) s : 0; }
/** * memchr - Find a character in an area of memory. * @s: The memory area * @c: The byte to search for * @n: The size of the area. * * returns the address of the first occurrence of @c, or %NULL * if @c is not found */ void *memchr(const void *s, int c, size_t n) { const unsigned char *src = (const unsigned char *) s; unsigned char d = c; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long *asrc; unsigned long mask; int i; while (UNALIGNED(src)) { if (!n--) return NULL; if (*src == d) return (void *) src; src++; } if (!TOO_SMALL(n)) { /* If we get this far, we know that length is large and src is word-aligned. */ /* The fast code reads the source one word at a time and only performs the bytewise search on word-sized segments if they contain the search character, which is detected by XORing the word-sized segment with a word-sized block of the search character and then detecting for the presence of NUL in the result. */ asrc = (unsigned long *) src; mask = d << 8 | d; mask = mask << 16 | mask; for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) mask = (mask << i) | mask; while (n >= LBLOCKSIZE) { if (DETECTCHAR(*asrc, mask)) break; n -= LBLOCKSIZE; asrc++; } /* If there are fewer than LBLOCKSIZE characters left, then we resort to the bytewise loop. */ src = (unsigned char *) asrc; } #endif /* not PREFER_SIZE_OVER_SPEED */ while (n--) { if (*src == d) return (void *) src; src++; } return NULL; }
/* Detect whether the character used to fill mask is in X */ #define DETECTCHAR(X,MASK) (DETECTNULL(X^MASK)) #endif /* OPTIMIZED_FOR_SIZE */ static char * strchr (const char *s, int c) { char pc = (char) c; #ifndef OPTIMIZED_FOR_SIZE const unsigned long *ps; unsigned long mask = 0; size_t i; /* Special case for finding \0. */ if (c == '\0') { while (UNALIGNED (s)) { if (*s == '\0') return (char *) s; ++s; } /* Operate a word at a time. */ ps = (const unsigned long *) s; while (!DETECTNULL (*ps)) ++ps; /* Found the end of the string. */ s = (const char *) ps; while (*s != '\0') ++s; return (char *) s; } /* All other bytes. Align the pointer, then search a long at a time. */ while (UNALIGNED (s)) { if (*s == '\0' || *s == pc) return *s ? (char *) s : 0; ++s; } ps = (const unsigned long *) s; for (i = 0; i < sizeof (unsigned long); ++i) mask = ((mask << CHAR_BIT) + ((unsigned char) pc & ~(~0 << CHAR_BIT))); /* Move ps a block at a time. */ while (!DETECTNULL (*ps) && !DETECTCHAR (*ps, mask)) ++ps; /* Pick up any residual with a byte searcher. */ s = (const char *) ps; #endif /* OPTIMIZED_FOR_SIZE */ /* The normal byte-search loop. */ while (*s && *s != pc) ++s; return *s == pc ? (char *) s : 0; }
char *strchr(const char *s1, int i) { const unsigned char *s = (const unsigned char *)s1; unsigned char c = i; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long mask,j; unsigned long *aligned_addr; /* Special case for finding 0. */ if (!c) { while (UNALIGNED (s)) { if (!*s) return (char *) s; s++; } /* Operate a word at a time. */ aligned_addr = (unsigned long *) s; while (!DETECTNULL (*aligned_addr)) aligned_addr++; /* Found the end of string. */ s = (const unsigned char *) aligned_addr; while (*s) s++; return (char *) s; } /* All other bytes. Align the pointer, then search a long at a time. */ while (UNALIGNED (s)) { if (!*s) return NULL; if (*s == c) return (char *) s; s++; } mask = c; for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) mask = (mask << j) | mask; aligned_addr = (unsigned long *) s; while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) aligned_addr++; /* The block of bytes currently pointed to by aligned_addr contains either a null or the target char, or both. We catch it using the bytewise search. */ s = (unsigned char *) aligned_addr; #endif /* not PREFER_SIZE_OVER_SPEED */ while (*s && *s != c) s++; if (*s == c) return (char *)s; return NULL; }