feat(string): add GNU strcasestr at level 3

Case-insensitive ASCII-fold substring search, locale-free, no
allocation.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <[email protected]>
This commit is contained in:
2026-08-31 21:14:52 -04:00
co-authored by Sisyphus
parent d5e390e992
commit e8fe84e27c
+59
View File
@@ -0,0 +1,59 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
/*
* Fold an ASCII uppercase letter to lowercase; every other character
* (including NUL) passes through unchanged. Kept local and locale-free:
* strcasestr must never depend on ctype tables or the active locale.
*/
static inline char
fold_ascii(char c)
{
if (c >= 'A' && c <= 'Z')
{
return (char)(c + ('a' - 'A'));
}
return c;
}
/*
* Return a pointer to the first case-insensitive (ASCII fold) occurrence of
* needle in haystack, or NULL if absent. An empty needle matches haystack.
*
* Naive two-pointer scan: for each position in haystack, compare folded
* characters until the needle is exhausted (match) or a mismatch occurs
* (advance). The inner loop stops at the NUL terminator of either string,
* so the comparison never reads past the end of haystack when needle is
* longer than the remaining tail.
*/
char *
strcasestr(const char *haystack, const char *needle) // NOLINT(bugprone-easily-swappable-parameters)
{
if (*needle == '\0')
{
return (char *)haystack;
}
for (; *haystack != '\0'; haystack++)
{
const char *h = haystack;
const char *n = needle;
while (*n != '\0' && fold_ascii(*h) == fold_ascii(*n))
{
h++;
n++;
}
if (*n == '\0')
{
return (char *)haystack;
}
}
return NULL;
}