From c0f80d42f0b8070420fd0f3b81d76007d97cee12 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Fri, 5 Feb 2021 13:40:23 +0100 Subject: Upgraded cstr impl. --- examples/words.c | 4 +-- stc/ccommon.h | 8 ++--- stc/cstr.h | 106 +++++++++++++++++++++++++++++-------------------------- 3 files changed, 61 insertions(+), 57 deletions(-) diff --git a/examples/words.c b/examples/words.c index 08563cfc..b3bd963f 100644 --- a/examples/words.c +++ b/examples/words.c @@ -1,4 +1,4 @@ - +#include #include #include #include @@ -16,7 +16,7 @@ int main1() "this", "sentence", "is", "a", "hoax" }); - clist_str_push_back(&lwords, cstr_from_fmt("%f", 123897.0 / 23.0)); + clist_str_push_back(&lwords, cstr_from_fmt("%.15f", sqrt(2))); c_foreach (w, clist_str, lwords) printf("%s\n", w.ref->str); puts(""); diff --git a/stc/ccommon.h b/stc/ccommon.h index bd2700ab..bea528bc 100644 --- a/stc/ccommon.h +++ b/stc/ccommon.h @@ -42,13 +42,13 @@ #if defined(STC_HEADER) || defined(STC_IMPLEMENTATION) # define STC_API extern # define STC_DEF -# define STC_API_V extern -# define STC_DEF_V +# define STC_LIBRARY_ONLY(...) __VA_ARGS__ +# define STC_STATIC_ONLY(...) #else # define STC_API static inline # define STC_DEF static inline -# define STC_API_V static -# define STC_DEF_V static +# define STC_LIBRARY_ONLY(...) +# define STC_STATIC_ONLY(...) __VA_ARGS__ #endif /* Macro overloading feature support: https://rextester.com/ONP80107 */ diff --git a/stc/cstr.h b/stc/cstr.h index 8c29c9b3..2a49bbda 100644 --- a/stc/cstr.h +++ b/stc/cstr.h @@ -33,11 +33,10 @@ typedef struct cstr { char* str; } cstr_t, cstr; typedef struct { char *ref; } cstr_iter_t; typedef char cstr_value_t; +#define cstr_npos ((size_t) (-1)) -#define cstr_size(s) ((const size_t *) (s).str)[-2] -#define cstr_capacity(s) ((const size_t *) (s).str)[-1] -#define cstr_empty(s) (cstr_size(s) == 0) -#define cstr_npos ((size_t) (-1)) +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_API cstr_t cstr_from_n(const char* str, size_t len); @@ -73,22 +72,21 @@ 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] -/* match common malloc_usable_size() sequence: 24, 40, 56, ... */ -#define _cstr_mem(size) ((((size) + 24) >> 4) * 16 + 8) -/* gives true string capacity: 7, 23, 39, ... */ -#define _cstr_cap(size) ((((size) + 24) >> 4) * 16 - 9) -static size_t _cstr_nullrep[3] = {0, 0, 0}; +/* 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, ... */ +#define _cstr_opt_cap(cap) (_cstr_opt_mem(cap) - offsetof(struct cstr_rep, str) - 1) -static const cstr_t cstr_inits = {(char* ) &_cstr_nullrep[2]}; +STC_LIBRARY_ONLY( extern const cstr_t cstr_inits; ) +STC_STATIC_ONLY( static struct cstr_rep _cstr_nullrep = {0, 0, {0}}; + static const cstr_t cstr_inits = {_cstr_nullrep.str}; ) STC_INLINE cstr_t cstr_init() { return cstr_inits; } STC_INLINE void cstr_del(cstr_t* self) { - if (cstr_capacity(*self)) + if (_cstr_rep(self)->cap) c_free(_cstr_rep(self)); } @@ -111,24 +109,24 @@ cstr_from(const char* str) { STC_INLINE cstr_t cstr_clone(cstr_t s) { - return cstr_from_n(s.str, cstr_size(s)); + return cstr_from_n(s.str, _cstr_rep(&s)->size); } STC_INLINE void cstr_clear(cstr_t* self) { - self->str[_cstr_size(*self) = 0] = '\0'; + self->str[_cstr_rep(self)->size = 0] = '\0'; } STC_INLINE char* cstr_front(cstr_t* self) {return self->str;} STC_INLINE char* -cstr_back(cstr_t* self) {return self->str + _cstr_size(*self) - 1;} +cstr_back(cstr_t* self) {return self->str + _cstr_rep(self)->size - 1;} STC_INLINE cstr_iter_t cstr_begin(cstr_t* self) {cstr_iter_t it = {self->str}; return it;} STC_INLINE cstr_iter_t cstr_end(cstr_t* self) { - cstr_iter_t it = {self->str + cstr_size(*self)}; return it; + cstr_iter_t it = {self->str + _cstr_rep(self)->size}; return it; } STC_INLINE void cstr_next(cstr_iter_t* it) { ++it->ref; } STC_INLINE char* cstr_itval(cstr_iter_t it) {return it.ref;} @@ -140,7 +138,7 @@ cstr_assign(cstr_t* self, const char* str) { STC_INLINE cstr_t* cstr_take(cstr_t* self, cstr_t s) { - if (self->str != s.str && cstr_capacity(*self)) + if (self->str != s.str && _cstr_rep(self)->cap) c_free(_cstr_rep(self)); self->str = s.str; return self; @@ -163,7 +161,7 @@ cstr_push_back(cstr_t* self, char value) { STC_INLINE void cstr_pop_back(cstr_t* self) { - self->str[ --_cstr_size(*self) ] = '\0'; + self->str[ --_cstr_rep(self)->size ] = '\0'; } STC_INLINE void @@ -188,8 +186,10 @@ cstr_getline(cstr_t *self, FILE *stream) { /* readonly */ -STC_INLINE size_t -cstr_length(cstr_t s) { return cstr_size(s); } +STC_INLINE size_t cstr_size(cstr_t s) {return _cstr_rep(&s)->size;} +STC_INLINE size_t cstr_capacity(cstr_t s) {return _cstr_rep(&s)->cap;} +STC_INLINE size_t cstr_empty(cstr_t s) {return _cstr_rep(&s)->size == 0;} +STC_INLINE size_t cstr_length(cstr_t s) { return _cstr_rep(&s)->size; } STC_INLINE bool cstr_equals(cstr_t s1, const char* str) { @@ -224,24 +224,24 @@ cstr_ibegins_with(cstr_t s, const char* needle) { STC_INLINE bool cstr_ends_with(cstr_t s, const char* needle) { - size_t n = strlen(needle), sz = cstr_size(s); + size_t n = strlen(needle), sz = _cstr_rep(&s)->size; return n <= sz ? memcmp(s.str + sz - n, needle, n) == 0 : false; } STC_INLINE bool cstr_iends_with(cstr_t s, const char* needle) { - size_t n = strlen(needle), sz = cstr_size(s); + size_t n = strlen(needle), sz = _cstr_rep(&s)->size; return n <= sz ? c_strncasecmp(s.str + sz - n, needle, n) == 0 : false; } /* cvec/cmap API functions: */ -STC_INLINE uint32_t c_string_hash(const char* str) { +STC_INLINE uint32_t +c_string_hash(const char* str) { uint32_t hash = 5381, c; /* djb2 */ const uint8_t* p = (const uint8_t*) str; while ((c = *p++)) hash = ((hash << 5) + hash) ^ c; return hash; } - STC_INLINE uint32_t cstr_hash_raw(const char* const* p, size_t none) { return c_string_hash(*p); @@ -258,33 +258,37 @@ uint32_t cstr_hash_raw(const char* const* p, size_t none) { #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) +STC_LIBRARY_ONLY( struct cstr_rep _cstr_nullrep = {0, 0, {0}}; + const cstr_t cstr_inits = {_cstr_nullrep.str}; ) + STC_DEF size_t cstr_reserve(cstr_t* self, size_t cap) { - size_t oldcap = cstr_capacity(*self); + struct cstr_rep* rep = _cstr_rep(self); + size_t oldcap = rep->cap; if (cap > oldcap) { - size_t* rep = (size_t *) c_realloc(oldcap ? _cstr_rep(self) : NULL, _cstr_mem(cap)); - self->str = (char *) &rep[2]; - if (oldcap == 0) self->str[rep[0] = 0] = '\0'; - return rep[1] = _cstr_cap(cap); + rep = (struct cstr_rep*) c_realloc(oldcap ? rep : NULL, _cstr_opt_mem(cap)); + self->str = rep->str; + if (oldcap == 0) self->str[rep->size = 0] = '\0'; + return (rep->cap = _cstr_opt_cap(cap)); } return oldcap; } STC_DEF void cstr_resize(cstr_t* self, size_t len, char fill) { - size_t n = cstr_size(*self); + size_t n = _cstr_rep(self)->size; cstr_reserve(self, len); if (len > n) memset(self->str + n, fill, len - n); - if (len | n) self->str[_cstr_size(*self) = len] = '\0'; + if (len | n) self->str[_cstr_rep(self)->size = len] = '\0'; } STC_DEF cstr_t cstr_from_n(const char* str, size_t len) { if (len == 0) return cstr_inits; - size_t *rep = (size_t *) c_malloc(_cstr_mem(len)); - cstr_t s = {strncpy((char *) &rep[2], str, len)}; - s.str[rep[0] = len] = '\0'; - rep[1] = _cstr_cap(len); + struct cstr_rep* rep = (struct cstr_rep*) c_malloc(_cstr_opt_mem(len)); + cstr_t s = {strncpy(rep->str, str, len)}; + s.str[rep->size = len] = '\0'; + rep->cap = _cstr_opt_cap(len); return s; } @@ -302,7 +306,7 @@ cstr_vfmt(cstr_t* self, const char* fmt, va_list args) { int len = vsnprintf(NULL, (size_t)0, fmt, args); cstr_reserve(self, len); vsprintf(self->str, fmt, args2); - _cstr_size(*self) = len; + _cstr_rep(self)->size = len; va_end(args2); } @@ -329,10 +333,10 @@ cstr_from_fmt(const char* fmt, ...) { STC_DEF cstr_t* cstr_assign_n(cstr_t* self, const char* str, size_t len) { - if (len || cstr_capacity(*self)) { + if (len || _cstr_rep(self)->cap) { cstr_reserve(self, len); memmove(self->str, str, len); - self->str[_cstr_size(*self) = len] = '\0'; + self->str[_cstr_rep(self)->size = len] = '\0'; } return self; } @@ -340,15 +344,15 @@ cstr_assign_n(cstr_t* self, const char* str, size_t len) { STC_DEF cstr_t* cstr_append_n(cstr_t* self, const char* str, size_t len) { if (len) { - size_t oldlen = cstr_size(*self), newlen = oldlen + len; - if (newlen > cstr_capacity(*self)) { + size_t oldlen = _cstr_rep(self)->size, newlen = oldlen + len; + if (newlen > _cstr_rep(self)->cap) { /* handle self append */ size_t off = (size_t) (str - self->str); cstr_reserve(self, newlen * 3 / 2); if (off <= oldlen) str = self->str + off; } memcpy(&self->str[oldlen], str, len); - self->str[_cstr_size(*self) = newlen] = '\0'; + self->str[_cstr_rep(self)->size = newlen] = '\0'; } return self; } @@ -356,11 +360,11 @@ cstr_append_n(cstr_t* self, const char* str, size_t len) { STC_INLINE void _cstr_internal_move(cstr_t* self, size_t pos1, size_t pos2) { if (pos1 == pos2) return; - size_t len = cstr_size(*self), newlen = len + pos2 - pos1; - if (newlen > cstr_capacity(*self)) + size_t len = _cstr_rep(self)->size, newlen = len + pos2 - pos1; + if (newlen > _cstr_rep(self)->cap) cstr_reserve(self, newlen * 3 / 2); memmove(&self->str[pos2], &self->str[pos1], len - pos1); - self->str[_cstr_size(*self) = newlen] = '\0'; + self->str[_cstr_rep(self)->size = newlen] = '\0'; } STC_DEF void @@ -374,16 +378,16 @@ cstr_replace_n(cstr_t* self, size_t pos, size_t len, const char* str, size_t n) STC_DEF void cstr_erase_n(cstr_t* self, size_t pos, size_t n) { - size_t len = cstr_size(*self); + size_t len = _cstr_rep(self)->size; if (len) { memmove(&self->str[pos], &self->str[pos + n], len - (pos + n)); - self->str[_cstr_size(*self) -= n] = '\0'; + self->str[_cstr_rep(self)->size -= n] = '\0'; } } STC_DEF bool cstr_getdelim(cstr_t *self, int delim, FILE *fp) { - size_t pos = 0, cap = cstr_capacity(*self); + size_t pos = 0, cap = _cstr_rep(self)->cap; int c = fgetc(fp); if (c == EOF) return false; @@ -391,7 +395,7 @@ cstr_getdelim(cstr_t *self, int delim, FILE *fp) { if (pos == cap) cap = cstr_reserve(self, cap * 3 / 2 + 34); if (c == delim || c == EOF) { - self->str[_cstr_size(*self) = pos] = '\0'; + self->str[_cstr_rep(self)->size = pos] = '\0'; return true; } self->str[pos++] = (char) c; @@ -406,13 +410,13 @@ cstr_find(cstr_t s, const char* needle) { } 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; + if (pos > _cstr_rep(&s)->size) 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; + if (pos > _cstr_rep(&s)->size) return cstr_npos; char* res = c_istrnfind(s.str + pos, needle, nlen); return res ? res - s.str : cstr_npos; } -- cgit v1.2.3