From 4436a1c0ac37dc2e73a2134d5ad85c010340b35d Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 17 Apr 2022 21:46:41 +0200 Subject: alt/cstr.h (sso string): added cstr_replace_all(). Header examples updated to use cstr_str(&s) instead of s.str. Some docs updates. --- README.md | 2 +- docs/cmap_api.md | 1 + docs/csmap_api.md | 1 + include/stc/alt/cstr.h | 56 ++++++++++++++++++++++++++++++++++++++++---------- include/stc/carc.h | 4 ++-- include/stc/cbox.h | 6 +++--- include/stc/csmap.h | 2 +- include/stc/cstr.h | 6 ++++-- include/stc/forward.h | 2 +- include/stc/utf8.h | 6 +++--- 10 files changed, 62 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index f59a156c..9b488fb6 100644 --- a/README.md +++ b/README.md @@ -320,7 +320,7 @@ can easier lead to mistakes. | non-emplace: Move | emplace: Embedded copy | Container | |:---------------------------|:-----------------------------|:--------------------------------------------| | insert() | emplace() | cmap, csmap, cset, csset | -| insert_or_assign(), put() | emplace_or_assign() | cmap, csmap | +| insert_or_assign(), put() | emplace_or_assign(), put_r() | cmap, csmap | | push() | emplace() | cqueue, cpque, cstack | | push_back(), push() | emplace_back() | cdeq, clist, cvec | | push_front() | emplace_front() | cdeq, clist | diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 493ee7cc..69d3d6db 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -71,6 +71,7 @@ cmap_X_result cmap_X_put(cmap_X* self, i_key key, i_val mapped); cmap_X_result cmap_X_emplace(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map cmap_X_result cmap_X_emplace_or_assign(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update rmapped +cmap_X_result cmap_X_put_r(cmap_X* self, i_keyraw rkey, i_valraw rmapped); // alias for emplace_or_assign size_t cmap_X_erase(cmap_X* self, i_keyraw rkey); // return 0 or 1 cmap_X_iter cmap_X_erase_at(cmap_X* self, cmap_X_iter it); // return iter after it diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 0b23878b..4bdcb42b 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -67,6 +67,7 @@ csmap_X_result csmap_X_put(csmap_X* self, i_key key, i_val mapped); csmap_X_result csmap_X_emplace(csmap_X* self, i_keyraw rkey, i_valraw rmapped); // no change if rkey in map csmap_X_result csmap_X_emplace_or_assign(csmap_X* self, i_keyraw rkey, i_valraw rmapped); // always update rmapped +csmap_X_result csmap_X_put_r(csmap_X* self, i_keyraw rkey, i_valraw rmapped); // alias for emplace_or_assign size_t csmap_X_erase(csmap_X* self, i_keyraw rkey); csmap_X_iter csmap_X_erase_at(csmap_X* self, csmap_X_iter it); // returns iter after it diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h index 37d6fcb5..409a7149 100644 --- a/include/stc/alt/cstr.h +++ b/include/stc/alt/cstr.h @@ -37,6 +37,12 @@ /**************************** PRIVATE API **********************************/ +#if defined __GNUC__ && !defined __clang__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Warray-bounds" +# pragma GCC diagnostic ignored "-Wstringop-overflow=" +#endif + enum { cstr_s_cap = sizeof(cstr_rep_t) - 1 }; #define cstr_s_size(s) ((size_t)(cstr_s_cap - (s)->sml.last)) #define cstr_s_set_size(s, len) ((s)->sml.last = cstr_s_cap - (len), (s)->sml.data[len] = 0) @@ -68,16 +74,17 @@ STC_API char* _cstr_internal_move(cstr* self, size_t pos1, size_t pos2); #define cstr_null (c_make(cstr){.sml = {.last = cstr_s_cap}}) #define cstr_toraw(self) cstr_str(self) -STC_API char* cstr_reserve(cstr* self, size_t cap); -STC_API void cstr_shrink_to_fit(cstr* self); -STC_API void cstr_resize(cstr* self, size_t size, char value); -STC_API size_t cstr_find_n(cstr s, const char* needle, size_t pos, size_t nmax); -STC_API cstr* cstr_assign_n(cstr* self, const char* str, size_t n); -STC_API cstr* cstr_append_n(cstr* self, const char* str, size_t n); -STC_API bool cstr_getdelim(cstr *self, int delim, FILE *fp); -STC_API void cstr_erase_n(cstr* self, size_t pos, size_t n); -STC_API cstr cstr_from_fmt(const char* fmt, ...); -STC_API int cstr_printf(cstr* self, const char* fmt, ...); +STC_API char* cstr_reserve(cstr* self, size_t cap); +STC_API void cstr_shrink_to_fit(cstr* self); +STC_API void cstr_resize(cstr* self, size_t size, char value); +STC_API size_t cstr_find_n(cstr s, const char* needle, size_t pos, size_t nmax); +STC_API cstr* cstr_assign_n(cstr* self, const char* str, size_t n); +STC_API cstr* cstr_append_n(cstr* self, const char* str, size_t n); +STC_API bool cstr_getdelim(cstr *self, int delim, FILE *fp); +STC_API void cstr_erase_n(cstr* self, size_t pos, size_t n); +STC_API cstr cstr_from_fmt(const char* fmt, ...); +STC_API int cstr_printf(cstr* self, const char* fmt, ...); +STC_API void cstr_replace_all(cstr* self, const char* find, const char* repl); STC_INLINE cstr_rep_t cstr_rep(cstr* s) { return cstr_is_long(s) @@ -367,6 +374,30 @@ STC_DEF bool cstr_getdelim(cstr *self, const int delim, FILE *fp) { } } +STC_DEF cstr +cstr_from_replace_all(const char* str, const size_t str_len, + const char* find, const size_t find_len, + const char* repl, const size_t repl_len) { + cstr out = cstr_null; + size_t from = 0; char* res; + if (find_len) + while ((res = c_strnstrn(str + from, find, str_len - from, find_len))) { + const size_t pos = res - str; + cstr_append_n(&out, str + from, pos - from); + cstr_append_n(&out, repl, repl_len); + from = pos + find_len; + } + cstr_append_n(&out, str + from, str_len - from); + return out; +} + +STC_DEF void +cstr_replace_all(cstr* self, const char* find, const char* repl) { + cstr_rep_t r = cstr_rep(self); + cstr_take(self, cstr_from_replace_all(r.data, r.size, find, strlen(find), + repl, strlen(repl))); +} + STC_DEF void cstr_erase_n(cstr* self, const size_t pos, size_t n) { cstr_rep_t r = cstr_rep(self); if (n > r.size - pos) n = r.size - pos; @@ -415,6 +446,9 @@ STC_DEF int cstr_printf(cstr* self, const char* fmt, ...) { return n; } +#endif // _i_implement +#if defined __GNUC__ && !defined __clang__ +# pragma GCC diagnostic pop #endif -#endif +#endif // CSTR_H_INCLUDED #undef i_opt diff --git a/include/stc/carc.h b/include/stc/carc.h index de78fe3b..374044f3 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -30,7 +30,7 @@ Person Person_new(const char* name, const char* last) { return (Person){.name = cstr_from(name), .last = cstr_from(last)}; } void Person_drop(Person* p) { - printf("drop: %s %s\n", p->name.str, p->last.str); + printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last)); c_drop(cstr, &p->name, &p->last); } @@ -43,7 +43,7 @@ int main() { carc_person p = carc_person_from(Person_new("John", "Smiths")); carc_person q = carc_person_clone(p); // share the pointer - printf("%s %s. uses: %" PRIuMAX "\n", q.get->name.str, q.get->last.str, *q.use_count); + printf("%s %s. uses: %" PRIuMAX "\n", cstr_str(&q.get->name), cstr_str(&q.get->last), *q.use_count); c_drop(carc_person, &p, &q); } */ diff --git a/include/stc/cbox.h b/include/stc/cbox.h index e43cf76c..d7c9ece9 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -35,7 +35,7 @@ Person Person_clone(Person p) { return p; } void Person_drop(Person* p) { - printf("drop: %s %s\n", p->name.str, p->email.str); + printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->email)); c_drop(cstr, &p->name, &p->email); } @@ -51,8 +51,8 @@ int main() { q = PBox_clone(p); cstr_assign(&q.get->name, "Joe Smiths"); - printf("%s %s.\n", p.get->name.str, p.get->email.str); - printf("%s %s.\n", q.get->name.str, q.get->email.str); + printf("%s %s.\n", cstr_str(&p.get->name), cstr_str(&p.get->email)); + printf("%s %s.\n", cstr_str(&q.get->name), cstr_str(&q.get->email)); } } */ diff --git a/include/stc/csmap.h b/include/stc/csmap.h index 682f123b..a043d896 100644 --- a/include/stc/csmap.h +++ b/include/stc/csmap.h @@ -44,7 +44,7 @@ int main(void) { csmap_sx_erase(&m, "Testing two"); c_foreach (i, csmap_sx, m) - printf("map %s: %g\n", i.ref->first.str, i.ref->second); + printf("map %s: %g\n", cstr_str(&i.ref->first), i.ref->second); } } */ diff --git a/include/stc/cstr.h b/include/stc/cstr.h index 8347778c..6a46791c 100644 --- a/include/stc/cstr.h +++ b/include/stc/cstr.h @@ -65,6 +65,7 @@ STC_API void cstr_erase_n(cstr* self, size_t pos, size_t n); STC_API size_t cstr_find(cstr s, const char* needle); STC_API size_t cstr_find_n(cstr s, const char* needle, size_t pos, size_t nmax); STC_API bool cstr_getdelim(cstr *self, int delim, FILE *stream); +STC_API void cstr_replace_all(cstr* self, const char* find, const char* repl); STC_INLINE cstr cstr_init() { return cstr_null; } #define cstr_toraw(self) (self)->str @@ -176,8 +177,8 @@ STC_INLINE int c_strncasecmp(const char* s1, const char* s2, size_t nmax) { #if defined(_i_implement) #ifndef _i_static -static struct cstr_priv _cstr_nullrep = {0, 0, {0}}; -const cstr cstr_null = {_cstr_nullrep.str}; +static cstr_priv _cstr_nullrep = {0, 0, {0}}; +const cstr cstr_null = {_cstr_nullrep.chr}; #endif STC_DEF char* @@ -373,3 +374,4 @@ cstr_find_n(cstr s, const char* needle, const size_t pos, const size_t nmax) { #endif #endif #endif +#undef i_opt \ No newline at end of file diff --git a/include/stc/forward.h b/include/stc/forward.h index 2351176a..0cefd271 100644 --- a/include/stc/forward.h +++ b/include/stc/forward.h @@ -46,7 +46,7 @@ typedef struct { char* data; size_t size, cap; } cstr_rep_t; typedef char cstr_value; #ifdef STC_USE_SSO typedef union { - struct { char data[sizeof(cstr_rep_t) - 1]; uint8_t last; } sml; + struct { char data[sizeof(cstr_rep_t) - 1]; unsigned char last; } sml; struct { char* data; size_t size, ncap; } lon; } cstr; #else diff --git a/include/stc/utf8.h b/include/stc/utf8.h index 7c4fdfc7..b8b4f27f 100644 --- a/include/stc/utf8.h +++ b/include/stc/utf8.h @@ -9,9 +9,9 @@ int main() { c_auto (cstr, s1) { s1 = cstr_new("hell😀 w😀rld"); - printf("%s\n", s1.str); - cstr_replace_sv(&s1, utf8_substr(s1.str, 7, 1), c_sv("🐨")); - printf("%s\n", s1.str); + printf("%s\n", cstr_str(&s1)); + cstr_replace_sv(&s1, utf8_substr(cstr_str(&s1), 7, 1), c_sv("🐨")); + printf("%s\n", cstr_str(&s1)); csview sv = csview_from_s(s1); c_foreach (i, csview, sv) -- cgit v1.2.3