From 560b6520ed0cb6f8faaf8309a87d4803b55a32c4 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 13 May 2021 18:24:53 +0200 Subject: Updated cstr: Added cstr_new(literal), Renamed cstr_assign_s() to cstr_copy(). Fixed and added minors in ccommon.h --- docs/cstr_api.md | 35 +++++++++++++++++++++------------- stc/carray.h | 2 +- stc/ccommon.h | 6 ++++-- stc/cstr.h | 57 ++++++++++++++++++++++++++++---------------------------- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/docs/cstr_api.md b/docs/cstr_api.md index 77fbe86c..308c54ab 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -16,6 +16,7 @@ All cstr definitions and prototypes are available by including a single header f ```c cstr cstr_init(void); // constructor +cstr cstr_new(const char literal_only[]); // constructor cstr cstr_with_capacity(size_t cap); cstr cstr_with_size(size_t len, char fill); // repeat fill len times cstr cstr_from(const char* str); @@ -37,9 +38,9 @@ void cstr_resize(cstr* self, size_t len, char fill); void cstr_clear(cstr* self); cstr* cstr_assign(cstr* self, const char* str); -cstr* cstr_assign_s(cstr* self, cstr s); // cstr_take(self, cstr_clone(s)) cstr* cstr_assign_n(cstr* self, const char* str, size_t n); // assign n first chars of str cstr* cstr_assign_fmt(cstr* self, const char* fmt, ...); // printf() formatting +cstr* cstr_copy(cstr* self, cstr s); // cstr_take(self, cstr_clone(s)) cstr* cstr_append(cstr* self, const char* str); cstr* cstr_append_s(cstr* self, cstr s); @@ -84,9 +85,13 @@ void cstr_next(cstr_iter_t* it); bool cstr_getline(cstr *self, FILE *stream); // cstr_getdelim(self, '\n', stream) bool cstr_getdelim(cstr *self, int delim, FILE *stream); ``` -Helper methods: + +Note that all methods with arguments `(..., const char* str, size_t n)`, `n` must be within the range of `str` length. + +#### Helper methods: ```c -const char* cstr_toraw(const cstr* x); +const char* cstr_toraw(const cstr* self); + 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); @@ -105,26 +110,30 @@ char* c_strncasestr(const char* str, const char* needle, size_t n); ## Constants and macros -| Name | Value | -|:------------------|:-----------------| -| `cstr_npos` | `(-1ull)` | +| Name | Value | +|:------------------|:------------------| +| `cstr_npos` | `((size_t) -1)` | +| `cstr_null | cstr null value | ## Example ```c #include int main() { - cstr s1 = cstr_from("one-nine-three-seven-five"); - printf("%s.\n", s1.str); + cstr s0 = cstr_new("Initialization without using strlen()."); + printf("%s\nLength: %zu\n\n", s0.str, cstr_size(s0)); + + cstr s1 = cstr_from("one-nine-three-seven-five."); + printf("%s\n", s1.str); cstr_insert(&s1, 3, "-two"); - printf("%s.\n", s1.str); + printf("%s\n", s1.str); cstr_erase_n(&s1, 7, 5); // -nine - printf("%s.\n", s1.str); + printf("%s\n", s1.str); - cstr_replace(&s1, cstr_find(&s1, "seven"), 5, "four"); - printf("%s.\n", s1.str); + cstr_replace(&s1, cstr_find(s1, "seven"), 5, "four"); + printf("%s\n", s1.str); // reassign: cstr_assign(&s1, "one two three four five six seven"); @@ -134,7 +143,7 @@ int main() { cstr full_path = cstr_from_fmt("%s/%s.%s", "directory", "filename", "ext"); printf("%s\n", full_path.str); - c_del(cstr, &s1, &full_path); + c_del(cstr, &s0, &s1, &full_path); } ``` Output: diff --git a/stc/carray.h b/stc/carray.h index 1e0d26c6..d61cbfcf 100644 --- a/stc/carray.h +++ b/stc/carray.h @@ -33,7 +33,7 @@ using_carray2(i, int); int main() { int w = 7, h = 5; - carray2i image = carray2i_init(w, h, 0); + carray2i image = carray2i_init(w, h); int *dat = carray2i_data(&image); for (int i = 0; i < carray2i_size(image); ++i) diff --git a/stc/ccommon.h b/stc/ccommon.h index 37458243..38015d16 100644 --- a/stc/ccommon.h +++ b/stc/ccommon.h @@ -43,7 +43,7 @@ # define STC_API extern # define STC_DEF # define STC_LIBRARY_ONLY(...) __VA_ARGS__ -# define STC_STATIC_ONLY(...) +# define STC_STATIC_ONLY(...) #else # define STC_API static inline # define STC_DEF static inline @@ -69,9 +69,11 @@ #if __cplusplus #define c_new(T) static_cast(c_malloc(sizeof(T))) #define c_new_n(T, n) static_cast(c_malloc(sizeof(T)*(n))) +#define c_cast(T) T #else #define c_new(T) c_malloc(sizeof(T)) -#define c_new_n(T, n) c_malloc(sizeof(T[n])) +#define c_new_n(T, n) c_malloc(sizeof(T)*(n)) +#define c_cast(T) (T) #endif #ifndef c_malloc #define c_malloc(sz) malloc(sz) diff --git a/stc/cstr.h b/stc/cstr.h index 7dc76058..890f6333 100644 --- a/stc/cstr.h +++ b/stc/cstr.h @@ -33,14 +33,15 @@ typedef struct { char* str; } cstr; typedef struct { char *ref; } cstr_iter_t; typedef char cstr_value_t; + #define cstr_npos ((size_t) (-1)) +STC_LIBRARY_ONLY( extern const cstr cstr_null; ) struct cstr_rep { size_t size, cap; char str[sizeof(size_t)]; }; #define _cstr_rep(self) c_container_of((self)->str, struct cstr_rep, str) -STC_LIBRARY_ONLY( extern const cstr cstr_inits; ) STC_STATIC_ONLY( static struct cstr_rep _cstr_nullrep = {0, 0, {0}}; - static const cstr cstr_inits = {_cstr_nullrep.str}; ) - + static const cstr cstr_null = {_cstr_nullrep.str}; ) +typedef const char strlit_t[]; /* optimal memory: based on malloc_usable_size() sequence: 24, 40, 56, ... */ #define _cstr_opt_mem(cap) ((((offsetof(struct cstr_rep, str) + (cap) + 8)>>4)<<4) + 8) /* optimal string capacity: 7, 23, 39, ... */ @@ -64,25 +65,27 @@ STC_API int c_strncasecmp(const char* s1, const char* s2, size_t n); STC_API char* c_strnstr(const char* s, const char* needle, size_t nmax); STC_API char* c_strncasestr(const char* s, const char* needle, size_t nmax); -STC_INLINE cstr cstr_init() { return cstr_inits; } +STC_INLINE cstr cstr_init() { return cstr_null; } +#define cstr_new(literal) \ + cstr_from_n(literal, sizeof c_cast(strlit_t){literal} - 1) +STC_INLINE cstr cstr_from(const char* str) + { return cstr_from_n(str, strlen(str)); } STC_INLINE size_t cstr_size(cstr s) { return _cstr_rep(&s)->size; } +STC_INLINE size_t cstr_length(cstr s) { return _cstr_rep(&s)->size; } STC_INLINE size_t cstr_capacity(cstr s) { return _cstr_rep(&s)->cap; } STC_INLINE size_t cstr_empty(cstr s) { return _cstr_rep(&s)->size == 0; } -STC_INLINE size_t cstr_length(cstr s) { return _cstr_rep(&s)->size; } STC_INLINE void cstr_del(cstr* self) { if (_cstr_rep(self)->cap) c_free(_cstr_rep(self)); } -STC_INLINE cstr cstr_from(const char* str) - { return cstr_from_n(str, cstr_npos); } STC_INLINE cstr cstr_clone(cstr s) { return cstr_from_n(s.str, _cstr_rep(&s)->size); } STC_INLINE void cstr_clear(cstr* self) { self->str[_cstr_rep(self)->size = 0] = '\0'; } STC_INLINE cstr* cstr_assign(cstr* self, const char* str) - { return cstr_assign_n(self, str, cstr_npos); } -STC_INLINE cstr* cstr_assign_s(cstr* self, cstr s) + { return cstr_assign_n(self, str, strlen(str)); } +STC_INLINE cstr* cstr_copy(cstr* self, cstr s) { return cstr_assign_n(self, s.str, _cstr_rep(&s)->size); } STC_INLINE cstr* cstr_append(cstr* self, const char* str) - { return cstr_append_n(self, str, cstr_npos); } + { return cstr_append_n(self, str, strlen(str)); } STC_INLINE cstr* cstr_append_s(cstr* self, cstr s) { return cstr_append_n(self, s.str, _cstr_rep(&s)->size); } STC_INLINE void cstr_push_back(cstr* self, char value) @@ -92,11 +95,11 @@ STC_INLINE void cstr_pop_back(cstr* self) STC_INLINE void cstr_insert_n(cstr* self, size_t pos, const char* str, size_t n) { cstr_replace_n(self, pos, 0, str, n); } STC_INLINE void cstr_insert(cstr* self, size_t pos, const char* str) - { cstr_replace_n(self, pos, 0, str, cstr_npos); } + { cstr_replace_n(self, pos, 0, str, strlen(str)); } STC_INLINE void cstr_insert_s(cstr* self, size_t pos, cstr s) { cstr_replace_n(self, pos, 0, s.str, _cstr_rep(&s)->size); } STC_INLINE void cstr_replace(cstr* self, size_t pos, size_t len, const char* str) - { cstr_replace_n(self, pos, len, str, cstr_npos); } + { cstr_replace_n(self, pos, len, str, strlen(str)); } STC_INLINE void cstr_replace_s(cstr* self, size_t pos, size_t len, cstr s) { cstr_replace_n(self, pos, len, s.str, _cstr_rep(&s)->size); } STC_INLINE void cstr_erase(cstr* self, size_t pos) @@ -105,9 +108,9 @@ STC_INLINE char* cstr_front(cstr* self) { return self->str; } STC_INLINE char* cstr_back(cstr* self) { return self->str + _cstr_rep(self)->size - 1; } STC_INLINE cstr_iter_t cstr_begin(cstr* self) - { cstr_iter_t it = {self->str}; return it; } + { return c_cast(cstr_iter_t){self->str}; } STC_INLINE cstr_iter_t cstr_end(cstr* self) - { cstr_iter_t it = {self->str + _cstr_rep(self)->size}; return it; } + { return c_cast(cstr_iter_t){self->str + _cstr_rep(self)->size}; } STC_INLINE void cstr_next(cstr_iter_t* it) {++it->ref; } STC_INLINE bool cstr_equals(cstr s1, const char* str) { return strcmp(s1.str, str) == 0; } @@ -128,14 +131,14 @@ STC_INLINE bool cstr_getline(cstr *self, FILE *stream) STC_INLINE cstr cstr_with_capacity(size_t cap) { - cstr s = cstr_inits; + cstr s = cstr_null; cstr_reserve(&s, cap); return s; } STC_INLINE cstr cstr_with_size(size_t len, char fill) { - cstr s = cstr_inits; + cstr s = cstr_null; cstr_resize(&s, len, fill); return s; } @@ -151,7 +154,7 @@ cstr_take(cstr* self, cstr s) { STC_INLINE cstr cstr_move(cstr* self) { cstr tmp = *self; - *self = cstr_inits; + *self = cstr_null; return tmp; } @@ -179,7 +182,7 @@ cstr_iends_with(cstr s, const char* needle) { #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) STC_LIBRARY_ONLY( static struct cstr_rep _cstr_nullrep = {0, 0, {0}}; - const cstr cstr_inits = {_cstr_nullrep.str}; ) + const cstr cstr_null = {_cstr_nullrep.str}; ) STC_DEF size_t cstr_reserve(cstr* self, size_t cap) { @@ -204,8 +207,7 @@ cstr_resize(cstr* self, size_t len, char fill) { STC_DEF cstr cstr_from_n(const char* str, size_t n) { - if (n == 0) return cstr_inits; - size_t sz = strlen(str); if (n > sz) n = sz; + if (n == 0) return cstr_null; struct cstr_rep* rep = (struct cstr_rep*) c_malloc(_cstr_opt_mem(n)); cstr s = {(char *) memcpy(rep->str, str, n)}; s.str[rep->size = n] = '\0'; @@ -240,7 +242,7 @@ cstr_vfmt(cstr* self, const char* fmt, va_list args) { STC_DEF cstr cstr_from_fmt(const char* fmt, ...) { - cstr ret = cstr_inits; + cstr ret = cstr_null; va_list args; va_start(args, fmt); cstr_vfmt(&ret, fmt, args); va_end(args); @@ -249,7 +251,7 @@ cstr_from_fmt(const char* fmt, ...) { STC_DEF cstr* cstr_assign_fmt(cstr* self, const char* fmt, ...) { - cstr ret = cstr_inits; + cstr ret = cstr_null; va_list args; va_start(args, fmt); cstr_vfmt(&ret, fmt, args); va_end(args); @@ -259,7 +261,6 @@ cstr_assign_fmt(cstr* self, const char* fmt, ...) { STC_DEF cstr* cstr_assign_n(cstr* self, const char* str, size_t n) { - size_t sz = strlen(str); if (n > sz) n = sz; if (n || _cstr_rep(self)->cap) { cstr_reserve(self, n); memmove(self->str, str, n); @@ -271,7 +272,6 @@ cstr_assign_n(cstr* self, const char* str, size_t n) { STC_DEF cstr* cstr_append_n(cstr* self, const char* str, size_t n) { if (n == 0) return self; - size_t sz = strlen(str); if (n > sz) n = sz; size_t oldlen = _cstr_rep(self)->size, newlen = oldlen + n; if (newlen > _cstr_rep(self)->cap) { size_t off = (size_t) (str - self->str); /* handle self append */ @@ -297,7 +297,6 @@ STC_DEF void cstr_replace_n(cstr* self, size_t pos, size_t len, const char* str, size_t n) { size_t sz = cstr_size(*self); if (len > sz - pos) len = sz - pos; - sz = strlen(str); if (n > sz) n = sz; c_withbuffer (xstr, char, n) { memcpy(xstr, str, n); _cstr_internal_move(self, pos + len, pos + n); @@ -307,15 +306,15 @@ 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 out = cstr_inits; - size_t find_len = strlen(find), from = 0, n = 0, pos; + 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(&out, replace); + cstr_append_n(&out, replace, repl_len); from = pos + find_len; ++n; } if (!n) return 0; - cstr_append(&out, self->str + from); + cstr_append_n(&out, self->str + from, cstr_size(*self) - from); cstr_del(self); *self = out; return n; } -- cgit v1.2.3