From ac726a3005409cffdac3788a09a1009604ee6f66 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Fri, 27 Nov 2020 09:10:39 +0100 Subject: Added and renamed case insensitive search functions. --- docs/cstr_api.md | 15 ++++--- stc/cstr.h | 117 +++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 89 insertions(+), 43 deletions(-) diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 547a2bea..30bff0c7 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -82,7 +82,8 @@ cstr_t* cstr_push_back( cstr_t* self, char ch ); (3) void cstr_insert( cstr_t* self, size_t pos, const char* str ); (1) void cstr_insert_n( cstr_t* self, size_t pos, const char* str, size_t n ); (2) ``` -Insert a string at the specified position (1), or insert string limited with +Insert a string at the specified position (1), or insert string limited with n / strlen(str). + ### Erase characters ```c void cstr_erase( cstr_t* self, size_t pos, size_t n ); @@ -99,18 +100,21 @@ void cstr_replace_n( cstr_t* self, size_t pos, size_t len, const char* s ```c size_t cstr_find( cstr_t s, const char* substr ); size_t cstr_find_n( cstr_t s, const char* substr, size_t pos, size_t nlen ); +size_t cstr_ifind_n( cstr_t s, const char* substr, size_t pos, size_t nlen ); bool cstr_contains( cstr_t s, const char* substr ); +bool cstr_icontains( cstr_t s, const char* substr ); bool cstr_begins_with( cstr_t s, const char* substr ); +bool cstr_ibegins_with( cstr_t s, const char* substr ); bool cstr_ends_with( cstr_t s, const char* substr ); +bool cstr_iends_with( cstr_t s, const char* substr ); ``` ### Comparisons and equality ```c bool cstr_equals( cstr_t s1, const char* str ); -bool cstr_equals_caseins( cstr_t s1, const char* str ); +bool cstr_iequals( cstr_t s1, const char* str ); bool cstr_equals_s( cstr_t s1, cstr_t s2 ); int cstr_compare( const cstr_t *s1, const cstr_t *s2 ); -int cstr_casecmp( const cstr_t *s1, const cstr_t *s2 ); ``` ### Get references to front and back of a cstr_t @@ -137,8 +141,9 @@ bool cstr_getdelim( cstr_t *self, int delim, FILE *stream ); ### Non-members ```c -char* c_strnfind( const char* s, const char* needle, size_t nlen ); -int c_strcasecmp( const char* s1, const char* s2 ); +int c_strncasecmp( const char* s1, const char* s2, size_t n ); +char* c_strnfind( const char* s, const char* needle, size_t nmax ); +char* c_istrnfind( const char* s, const char* needle, size_t nmax ); uint32_t c_string_hash( const char* str ); ``` diff --git a/stc/cstr.h b/stc/cstr.h index 3ec55451..def10d98 100644 --- a/stc/cstr.h +++ b/stc/cstr.h @@ -61,8 +61,19 @@ STC_API void cstr_erase(cstr_t* self, size_t pos, size_t n); STC_API bool cstr_getdelim(cstr_t *self, int delim, FILE *stream); +STC_API size_t +cstr_find(cstr_t s, const char* needle); +STC_API size_t +cstr_find_n(cstr_t s, const char* needle, size_t pos, size_t nlen); +STC_API size_t +cstr_ifind_n(cstr_t s, const char* needle, size_t pos, size_t nlen); + +STC_API int +c_strncasecmp(const char* s1, const char* s2, size_t n); STC_API char* -c_strnfind(const char* s, const char* needle, size_t nlen); +c_strnfind(const char* s, const char* needle, size_t nmax); +STC_DEF char* +c_istrnfind(const char* s, const char* needle, size_t nmax); #define _cstr_rep(self) (((size_t *) (self)->str) - 2) #define _cstr_size(s) ((size_t *) (s).str)[-2] @@ -174,20 +185,13 @@ cstr_getline(cstr_t *self, FILE *stream) { STC_INLINE size_t cstr_length(cstr_t s) { return cstr_size(s); } -STC_INLINE int -c_strcasecmp(const char* s1, const char* s2) { - while (*s1 && tolower(*s1) == tolower(*s2)) - ++s1, ++s2; - return tolower(*s1) - tolower(*s2); -} - STC_INLINE bool cstr_equals(cstr_t s1, const char* str) { return strcmp(s1.str, str) == 0; } STC_INLINE bool -cstr_equals_caseins(cstr_t s1, const char* str) { - return c_strcasecmp(s1.str, str) == 0; +cstr_iequals(cstr_t s1, const char* str) { + return c_strncasecmp(s1.str, str, cstr_npos) == 0; } STC_INLINE bool cstr_equals_s(cstr_t s1, cstr_t s2) { @@ -197,39 +201,35 @@ STC_INLINE int cstr_compare(const cstr_t *s1, const cstr_t *s2) { return strcmp(s1->str, s2->str); } -STC_INLINE int -cstr_casecmp(const cstr_t *s1, const cstr_t *s2) { - return c_strcasecmp(s1->str, s2->str); -} - -STC_INLINE size_t -cstr_find(cstr_t s, const char* needle) { - char* res = strstr(s.str, needle); - return res ? res - s.str : cstr_npos; -} -STC_INLINE size_t -cstr_find_n(cstr_t s, const char* needle, size_t pos, size_t nlen) { - if (pos > cstr_size(s)) return cstr_npos; - char* res = c_strnfind(s.str + pos, needle, nlen); - return res ? res - s.str : cstr_npos; -} STC_INLINE bool cstr_contains(cstr_t s, const char* needle) { return strstr(s.str, needle) != NULL; } +STC_INLINE bool +cstr_icontains(cstr_t s, const char* needle) { + return c_istrnfind(s.str, needle, cstr_npos) != NULL; +} + STC_INLINE bool cstr_begins_with(cstr_t s, const char* needle) { - for (;;) { - if (!(*needle && *s.str)) return *needle == 0; - if (*needle++ != *s.str++) return false; - } + return strncmp(s.str, needle, strlen(needle)) == 0; } +STC_INLINE bool +cstr_ibegins_with(cstr_t s, const char* needle) { + return c_strncasecmp(s.str, needle, strlen(needle)) == 0; +} + STC_INLINE bool cstr_ends_with(cstr_t s, const char* needle) { size_t n = strlen(needle), sz = cstr_size(s); return n <= sz ? strcmp(s.str + sz - n, needle) == 0 : false; } +STC_INLINE bool +cstr_iends_with(cstr_t s, const char* needle) { + size_t n = strlen(needle), sz = cstr_size(s); + return n <= sz ? c_strncasecmp(s.str + sz - n, needle, cstr_npos) == 0 : false; +} /* cvec/cmap API functions: */ @@ -399,24 +399,65 @@ cstr_getdelim(cstr_t *self, int delim, FILE *fp) { } } +STC_DEF size_t +cstr_find(cstr_t s, const char* needle) { + char* res = strstr(s.str, needle); + return res ? res - s.str : cstr_npos; +} +STC_DEF size_t +cstr_find_n(cstr_t s, const char* needle, size_t pos, size_t nlen) { + if (pos > cstr_size(s)) return cstr_npos; + char* res = c_strnfind(s.str + pos, needle, nlen); + return res ? res - s.str : cstr_npos; +} +STC_DEF size_t +cstr_ifind_n(cstr_t s, const char* needle, size_t pos, size_t nlen) { + if (pos > cstr_size(s)) return cstr_npos; + char* res = c_istrnfind(s.str + pos, needle, nlen); + return res ? res - s.str : cstr_npos; +} + +STC_DEF int +c_strncasecmp(const char* s1, const char* s2, size_t n) { + while (n && *s1 && tolower(*s1) == tolower(*s2)) + ++s1, ++s2, --n; + return n ? tolower(*s1) - tolower(*s2) : 0; +} + STC_DEF char* -c_strnfind(const char* s, const char* needle, size_t nlen) { +c_strnfind(const char* s, const char* needle, size_t nmax) { ptrdiff_t sum = 0; - const char *t = s, *p = needle, *q = p + nlen; - while (p != q) { - if (!(*t && *p)) - return NULL; + const char *t = s, *p = needle; + while (*p && nmax--) { + if (!*t) return NULL; sum += *t++ - *p++; } + nmax = t - s; for (;;) { - if (sum == 0 && memcmp(s, needle, nlen) == 0) + if (sum == 0 && memcmp(s, needle, nmax) == 0) return (char *) s; - if (!*t) - return NULL; + if (!*t) return NULL; sum += *t++ - *s++; } } +STC_DEF char* +c_istrnfind(const char* s, const char* needle, size_t nmax) { + ptrdiff_t sum = 0; + const char *t = s, *p = needle; + while (*p && nmax--) { + if (!*t) return NULL; + sum += tolower(*t++) - tolower(*p++); + } + nmax = t - s; + for (;;) { + if (sum == 0 && c_strncasecmp(s, needle, nmax) == 0) + return (char *) s; + if (!*t) return NULL; + sum += tolower(*t++) - tolower(*s++); + } +} + #endif #endif \ No newline at end of file -- cgit v1.2.3