[core] Add portable strcasestr implementation named str_contains_ignore_case (#18497)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
guillempages
2026-08-20 17:28:17 -05:00
committed by GitHub
co-authored by J. Nick Koston
parent 5177972c04
commit 46f90d0c54
4 changed files with 79 additions and 1 deletions
+13
View File
@@ -220,6 +220,19 @@ bool str_endswith_ignore_case(const char *str, size_t str_len, const char *suffi
return strncasecmp(str + str_len - suffix_len, suffix, suffix_len) == 0;
}
bool str_contains_ignore_case_fallback(const char *haystack, const char *needle) {
const size_t needle_len = strlen(needle);
if (needle_len == 0) {
return true;
}
for (const char *p = haystack; *p != '\0'; p++) {
if (strncasecmp(p, needle, needle_len) == 0) {
return true;
}
}
return false;
}
// str_truncate, str_until, str_lower_case, str_upper_case, str_snake_case moved to alloc_helpers.cpp
char *str_sanitize_to(char *buffer, size_t buffer_size, const char *str) {
if (buffer_size == 0) {
+19
View File
@@ -981,6 +981,25 @@ inline bool str_endswith_ignore_case(const std::string &str, const char *suffix)
return str_endswith_ignore_case(str.c_str(), str.size(), suffix, strlen(suffix));
}
/// Fallback implementation for case insensitive substring comparison.
bool str_contains_ignore_case_fallback(const char *haystack, const char *needle);
/// Case-insensitive check if needle string is contained in haystack (no heap allocation).
inline bool str_contains_ignore_case(const char *haystack, const char *needle) {
if (!needle || !haystack) {
return false;
}
// strcasestr is a GNU extension: newlib only declares it when _GNU_SOURCE is set.
// ESP32/ESP8266/host builds get it from their framework or from g++ on Linux;
// LibreTiny, RP2 and Zephyr do not, so they use the hand-rolled fallback.
#if defined(USE_LIBRETINY) || defined(USE_RP2) || defined(USE_ZEPHYR)
return str_contains_ignore_case_fallback(haystack, needle);
#else // defined(USE_LIBRETINY) || defined(USE_RP2) || defined(USE_ZEPHYR)
return strcasestr(haystack, needle) != nullptr;
#endif // defined(USE_LIBRETINY) || defined(USE_RP2) || defined(USE_ZEPHYR)
}
// str_truncate moved to alloc_helpers.h - remove this include before 2026.11.0
// str_until, str_lower_case, str_upper_case moved to alloc_helpers.h - remove this comment before 2026.11.0