summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2021-06-15 09:51:49 +0200
committerTyge Løvset <[email protected]>2021-06-15 09:51:49 +0200
commit0e52b558cbe7cd3ac54bf3aba88c5679c43d6e39 (patch)
tree40df20188fb374d50c8411c14cccf0fafc27f65d
parentb8f24b90481d83d06ae89e2594c249c9741dae21 (diff)
downloadSTC-modified-0e52b558cbe7cd3ac54bf3aba88c5679c43d6e39.tar.gz
STC-modified-0e52b558cbe7cd3ac54bf3aba88c5679c43d6e39.zip
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.
-rw-r--r--docs/cstr_api.md4
-rw-r--r--docs/csview_api.md2
-rw-r--r--include/stc/cstr.h47
-rw-r--r--include/stc/csview.h86
4 files changed, 89 insertions, 50 deletions
diff --git a/docs/cstr_api.md b/docs/cstr_api.md
index 8dec7f2f..cdb73a69 100644
--- a/docs/cstr_api.md
+++ b/docs/cstr_api.md
@@ -96,8 +96,8 @@ int c_rawstr_compare(const char** x, const char** y);
bool c_rawstr_equals(const char** x, const char** y);
uint64_t c_rawstr_hash(const char* const* x, size_t ignored);
int c_strncasecmp(const char* str1, const char* str2, size_t n);
-char* c_strnstrn(const char* str, const char* needle, size_t slen, size_t nmax);
-char* c_strncasestrn(const char* str, const char* needle, size_t slen, size_t nmax);
+char* c_strnstrn(const char* str, const char* needle, size_t slen, size_t nlen);
+char* c_strncasestrn(const char* str, const char* needle, size_t slen, size_t nlen);
```
## Types
diff --git a/docs/csview_api.md b/docs/csview_api.md
index ba2697bd..bd4945c0 100644
--- a/docs/csview_api.md
+++ b/docs/csview_api.md
@@ -58,6 +58,7 @@ void csview_next(csview_iter_t* it);
#### Extended cstr methods
```c
cstr cstr_from_v(csview sv); // construct cstr from csview
+cstr cstr_from_replace_all(csview sv, csview find, csview replace);
csview cstr_sv(cstr s); // convert to csview from cstr
csview cstr_to_v(const cstr* self); // convert to csview from cstr*
@@ -68,6 +69,7 @@ cstr* cstr_assign_v(cstr* self, csview sv);
cstr* cstr_append_v(cstr* self, csview sv);
void cstr_insert_v(cstr* self, size_t pos, csview sv);
void cstr_replace_v(cstr* self, size_t pos, size_t len, csview sv);
+void cstr_replace_all_v(cstr* self, csview find, csview replace);
bool cstr_equals_v(cstr s, csview sv);
size_t cstr_find_v(cstr s, csview needle);
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