From 0e52b558cbe7cd3ac54bf3aba88c5679c43d6e39 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 15 Jun 2021 09:51:49 +0200 Subject: Fixed c_strnstrn() and cstr_find_n() bugs. when find string is empty. Added cstr_from_replace_all() and cstr_replace_all_v() to do replace-all from csview inputs. --- include/stc/cstr.h | 47 ++++++++++++++-------------- include/stc/csview.h | 86 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 85 insertions(+), 48 deletions(-) (limited to 'include') diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 89d3921c..26d71f91 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -63,8 +63,8 @@ STC_API size_t cstr_ifind_n(cstr s, const char* needle, size_t pos, siz STC_API bool cstr_getdelim(cstr *self, int delim, FILE *stream); STC_API int c_strncasecmp(const char* s1, const char* s2, size_t nmax); -STC_API char* c_strnstrn(const char* s, const char* needle, size_t slen, size_t nmax); -STC_API char* c_strncasestrn(const char* s, const char* needle, size_t slen, size_t nmax); +STC_API char* c_strnstrn(const char* s, const char* needle, size_t slen, size_t nlen); +STC_API char* c_strncasestrn(const char* s, const char* needle, size_t slen, size_t nlen); STC_INLINE cstr cstr_init() { return cstr_null; } #define cstr_lit(literal) \ @@ -314,16 +314,19 @@ cstr_replace_n(cstr* self, size_t pos, size_t len, const char* str, size_t n) { } STC_DEF size_t -cstr_replace_all(cstr* self, const char* find, const char* replace) { +cstr_replace_all(cstr* self, const char* find, const char* repl) { cstr out = cstr_null; - size_t find_len = strlen(find), repl_len = strlen(replace), from = 0, n = 0, pos; - while ((pos = cstr_find_n(*self, find, from, cstr_npos)) != cstr_npos) { - cstr_append_n(&out, self->str + from, pos - from ); - cstr_append_n(&out, replace, repl_len); + size_t len = cstr_size(*self), find_len = strlen(find), repl_len = strlen(repl); + size_t from = 0, n = 0, pos; char* res; + if (!find_len) return 0; + while ((res = c_strnstrn(self->str + from, find, len - from, find_len))) { + pos = res - self->str; + cstr_append_n(&out, self->str + from, pos - from); + cstr_append_n(&out, repl, repl_len); from = pos + find_len; ++n; } if (!n) return 0; - cstr_append_n(&out, self->str + from, cstr_size(*self) - from); + cstr_append_n(&out, self->str + from, len - from); cstr_del(self); *self = out; return n; } @@ -365,14 +368,16 @@ cstr_find(cstr s, const char* needle) { STC_DEF size_t cstr_find_n(cstr s, const char* needle, size_t pos, size_t nmax) { if (pos > _cstr_rep(&s)->size) return cstr_npos; - char* res = c_strnstrn(s.str + pos, needle, _cstr_rep(&s)->size - pos, nmax); + size_t nlen = strlen(needle); + char* res = c_strnstrn(s.str + pos, needle, _cstr_rep(&s)->size - pos, nmax < nlen ? nmax : nlen); return res ? res - s.str : cstr_npos; } STC_DEF size_t cstr_ifind_n(cstr s, const char* needle, size_t pos, size_t nmax) { if (pos > _cstr_rep(&s)->size) return cstr_npos; - char* res = c_strncasestrn(s.str + pos, needle, _cstr_rep(&s)->size - pos, nmax); + size_t nlen = strlen(needle); + char* res = c_strncasestrn(s.str + pos, needle, _cstr_rep(&s)->size - pos, nmax < nlen ? nmax : nlen); return res ? res - s.str : cstr_npos; } @@ -384,26 +389,24 @@ c_strncasecmp(const char* s1, const char* s2, size_t nmax) { } STC_DEF char* -c_strnstrn(const char *s, const char *needle, size_t slen, size_t nmax) { - size_t n = strlen(needle); - if (nmax < n) n = nmax; - if (n > slen) return NULL; - slen -= n; +c_strnstrn(const char *s, const char *needle, size_t slen, size_t nlen) { + if (!nlen) return (char *)s; + if (nlen > slen) return NULL; + slen -= nlen; do { - if (*s == *needle && !memcmp(s, needle, n)) return (char *)s; + if (*s == *needle && !memcmp(s, needle, nlen)) return (char *)s; ++s; } while (slen--); return NULL; } STC_DEF char* -c_strncasestrn(const char *s, const char *needle, size_t slen, size_t nmax) { - size_t n = strlen(needle); - if (nmax < n) n = nmax; - if (n > slen) return NULL; - int c = tolower(*needle); slen -= n; +c_strncasestrn(const char *s, const char *needle, size_t slen, size_t nlen) { + if (!nlen) return (char *)s; + if (nlen > slen) return NULL; + int c = tolower(*needle); slen -= nlen; do { - if (tolower(*s) == c && !c_strncasecmp(s, needle, n)) return (char *)s; + if (tolower(*s) == c && !c_strncasecmp(s, needle, nlen)) return (char *)s; ++s; } while (slen--); return NULL; diff --git a/include/stc/csview.h b/include/stc/csview.h index 04133437..9b65d2e3 100644 --- a/include/stc/csview.h +++ b/include/stc/csview.h @@ -36,6 +36,11 @@ typedef char csview_value_t; #define c_sv(literal) csview_lit(literal) #define cstr_sv(s) csview_from_s(s) +STC_API csview csview_substr(csview sv, intptr_t pos, size_t n); +STC_API csview csview_slice(csview sv, intptr_t p1, intptr_t p2); +STC_API csview csview_first_token(csview sv, csview sep); +STC_API csview csview_next_token(csview sv, csview sep, csview tok); + #define csview_lit(literal) \ c_make(csview){literal, sizeof c_make(strlit_t){literal} - 1} STC_INLINE csview csview_from(const char* str) @@ -72,35 +77,11 @@ STC_INLINE csview_iter_t csview_end(const csview* self) { return c_make(csview_iter_t){self->str + self->size}; } STC_INLINE void csview_next(csview_iter_t* it) { ++it->ref; } -STC_INLINE csview csview_substr(csview sv, intptr_t pos, size_t n) { - if (pos < 0) { pos += sv.size; if (pos < 0) pos = 0; } - if (pos > sv.size) pos = sv.size; if (pos + n > sv.size) n = sv.size - pos; - sv.str += pos, sv.size = n; return sv; -} - -STC_INLINE csview csview_slice(csview sv, intptr_t p1, intptr_t p2) { - if (p1 < 0) { p1 += sv.size; if (p1 < 0) p1 = 0; } - if (p2 < 0) p2 += sv.size; if (p2 > sv.size) p2 = sv.size; - sv.str += p1, sv.size = p2 > p1 ? p2 - p1 : 0; return sv; -} - -STC_INLINE csview csview_first_token(csview sv, csview sep) { - const char* res = c_strnstrn(sv.str, sep.str, sv.size, sep.size); - return c_make(csview){sv.str, (res ? res - sv.str : sv.size)}; -} - -STC_INLINE csview csview_next_token(csview sv, csview sep, csview tok) { - if (&tok.str[tok.size] == &sv.str[sv.size]) - return c_make(csview){&sv.str[sv.size], 0}; - tok.str += tok.size + sep.size; - size_t n = sv.size - (tok.str - sv.str); - const char* res = c_strnstrn(tok.str, sep.str, n, sep.size); - tok.size = res ? res - tok.str : n; - return tok; -} /* cstr interaction with csview: */ +STC_API cstr cstr_from_replace_all(csview sv, csview find, csview replace); + STC_INLINE cstr cstr_from_v(csview sv) { return cstr_from_n(sv.str, sv.size); } STC_INLINE csview cstr_to_v(const cstr* self) @@ -117,6 +98,8 @@ STC_INLINE void cstr_insert_v(cstr* self, size_t pos, csview sv) { cstr_replace_n(self, pos, 0, sv.str, sv.size); } STC_INLINE void cstr_replace_v(cstr* self, size_t pos, size_t len, csview sv) { cstr_replace_n(self, pos, len, sv.str, sv.size); } +STC_INLINE void cstr_replace_all_v(cstr* self, csview find, csview replace) + { cstr_take(self, cstr_from_replace_all(cstr_sv(*self), find, replace)); } STC_INLINE bool cstr_equals_v(cstr s, csview sv) { return sv.size == cstr_size(s) && !memcmp(s.str, sv.str, sv.size); } STC_INLINE size_t cstr_find_v(cstr s, csview needle) @@ -183,4 +166,55 @@ STC_INLINE bool csview_equals_ref(const csview* a, const csview* b) _c_using_chash(cset_strv, cset_, cstr, cstr, csview_equals_ref, csview_hash_ref, \ @@, @@, @@, void, c_true, cstr_del, cstr_from_v, cstr_to_v, csview) +/* -------------------------- IMPLEMENTATION ------------------------- */ + +#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) + +STC_DEF csview +csview_substr(csview sv, intptr_t pos, size_t n) { + if (pos < 0) { pos += sv.size; if (pos < 0) pos = 0; } + if (pos > sv.size) pos = sv.size; if (pos + n > sv.size) n = sv.size - pos; + sv.str += pos, sv.size = n; return sv; +} + +STC_DEF csview +csview_slice(csview sv, intptr_t p1, intptr_t p2) { + if (p1 < 0) { p1 += sv.size; if (p1 < 0) p1 = 0; } + if (p2 < 0) p2 += sv.size; if (p2 > sv.size) p2 = sv.size; + sv.str += p1, sv.size = p2 > p1 ? p2 - p1 : 0; return sv; +} + +STC_DEF csview +csview_first_token(csview sv, csview sep) { + const char* res = c_strnstrn(sv.str, sep.str, sv.size, sep.size); + return c_make(csview){sv.str, (res ? res - sv.str : sv.size)}; +} + +STC_DEF csview +csview_next_token(csview sv, csview sep, csview tok) { + if (&tok.str[tok.size] == &sv.str[sv.size]) + return c_make(csview){&sv.str[sv.size], 0}; + tok.str += tok.size + sep.size; + size_t n = sv.size - (tok.str - sv.str); + const char* res = c_strnstrn(tok.str, sep.str, n, sep.size); + tok.size = res ? res - tok.str : n; + return tok; +} + +STC_DEF cstr +cstr_from_replace_all(csview sv, csview find, csview replace) { + cstr out = cstr_null; + size_t from = 0, pos; char* res; + if (find.size) + while ((res = c_strnstrn(sv.str + from, find.str, sv.size - from, find.size))) { + pos = res - sv.str; + cstr_append_n(&out, sv.str + from, pos - from ); + cstr_append_v(&out, replace); + from = pos + find.size; + } + cstr_append_n(&out, sv.str + from, sv.size - from); + return out; +} + +#endif #endif \ No newline at end of file -- cgit v1.2.3