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:
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user