From 92b950333c6c7002bdbf1b60af44a249dc0cef9c Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sun, 19 Dec 2021 12:21:44 +0100 Subject: First commit for Version 3 of STC. Main changes are consistent rename of '_del' to '_drop' and '_compare' to '_cmp'. Also i_key_ref (earlier i_key_sptr) and i_val_ref replaced by more general i_key_bind/i_val_bind. --- include/stc/alt/clist.h | 18 +-- include/stc/alt/csmap.h | 30 ++-- include/stc/alt/cstr.h | 27 ++-- include/stc/alt/sstr.h | 406 ------------------------------------------------ 4 files changed, 38 insertions(+), 443 deletions(-) delete mode 100644 include/stc/alt/sstr.h (limited to 'include/stc/alt') diff --git a/include/stc/alt/clist.h b/include/stc/alt/clist.h index 6695a26e..14abc7e4 100644 --- a/include/stc/alt/clist.h +++ b/include/stc/alt/clist.h @@ -49,7 +49,7 @@ puts("sorted"); c_foreach (i, clist_ix, list) if (++n % 10000 == 0) printf("%8d: %10zd\n", n, i.ref->value); - clist_ix_del(&list); + clist_ix_drop(&list); } */ #include @@ -61,13 +61,13 @@ _c_clist_types(clist_VOID, int); STC_API size_t _clist_count(const clist_VOID* self); #define _clist_node(_cx_self, vp) c_container_of(vp, _cx_node, value) -#define _c_using_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw, defTypes) \ +#define _c_using_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw, defTypes) \ \ defTypes( _c_clist_types(_cx_self, i_val); ) \ typedef i_valraw _cx_rawvalue; \ \ STC_API _cx_self _cx_memb(_clone)(_cx_self lst); \ - STC_API void _cx_memb(_del)(_cx_self* self); \ + STC_API void _cx_memb(_drop)(_cx_self* self); \ STC_API void _cx_memb(_push_back)(_cx_self* self, i_val value); \ STC_API void _cx_memb(_push_front)(_cx_self* self, i_val value); \ STC_API void _cx_memb(_emplace_items)(_cx_self *self, const _cx_rawvalue arr[], size_t n); \ @@ -89,7 +89,7 @@ STC_API size_t _clist_count(const clist_VOID* self); STC_INLINE size_t _cx_memb(_count)(_cx_self lst) { return _clist_count((const clist_VOID*) &lst); } \ STC_INLINE i_val _cx_memb(_value_fromraw)(i_valraw raw) { return i_valfrom(raw); } \ STC_INLINE i_val _cx_memb(_value_clone)(i_val val) { return i_valfrom(i_valto(&val)); } \ - STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_del)(self); } \ + STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_drop)(self); } \ STC_INLINE void _cx_memb(_emplace_back)(_cx_self* self, i_valraw raw) \ { _cx_memb(_push_back)(self, i_valfrom(raw)); } \ STC_INLINE void _cx_memb(_emplace_front)(_cx_self* self, i_valraw raw) \ @@ -143,13 +143,13 @@ STC_API size_t _clist_count(const clist_VOID* self); while (n-- && it.ref) _cx_memb(_next)(&it); return it; \ } \ \ - _c_implement_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw) \ + _c_implement_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) -#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw) \ +#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw) \ \ STC_DEF _cx_self \ _cx_memb(_clone)(_cx_self lst) { \ @@ -160,7 +160,7 @@ STC_API size_t _clist_count(const clist_VOID* self); } \ \ STC_DEF void \ - _cx_memb(_del)(_cx_self* self) { \ + _cx_memb(_drop)(_cx_self* self) { \ while (self->last) _cx_memb(_erase_after_)(self, self->last); \ } \ \ @@ -232,7 +232,7 @@ STC_API size_t _clist_count(const clist_VOID* self); node->next = next; \ if (del == next) self->last = node = NULL; \ else if (self->last == del) self->last = node, node = NULL; \ - i_valdel(&del->value); c_free(del); \ + i_valdrop(&del->value); c_free(del); \ return node; \ } \ \ @@ -361,7 +361,7 @@ _clist_mergesort(clist_VOID_node *list, int (*cmp)(const void*, const void*)) { } #else -#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdel, i_valfrom, i_valto, i_valraw) +#define _c_implement_clist(_cx_self, i_val, i_cmp, i_valdrop, i_valfrom, i_valto, i_valraw) #endif #endif diff --git a/include/stc/alt/csmap.h b/include/stc/alt/csmap.h index 5b331efb..beccf559 100644 --- a/include/stc/alt/csmap.h +++ b/include/stc/alt/csmap.h @@ -30,7 +30,7 @@ using_csmap(mx, int, char); // Sorted map int main(void) { - c_autovar (csmap_mx m = csmap_mx_init(), csmap_mx_del(&m)) + c_autovar (csmap_mx m = csmap_mx_init(), csmap_mx_drop(&m)) { csmap_mx_insert(&m, 5, 'a'); csmap_mx_insert(&m, 8, 'b'); @@ -91,8 +91,8 @@ int main(void) { \ STC_INLINE bool _cx_memb(_empty)(_cx_self cx) { return cx.size == 0; } \ STC_INLINE size_t _cx_memb(_size)(_cx_self cx) { return cx.size; } \ - STC_INLINE void _cx_memb(_del)(_cx_self* self) { _cx_memb(_del_r_)(self->root); } \ - STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_del)(self); *self = _cx_memb(_init)(); } \ + STC_INLINE void _cx_memb(_drop)(_cx_self* self) { _cx_memb(_del_r_)(self->root); } \ + STC_INLINE void _cx_memb(_clear)(_cx_self* self) { _cx_memb(_drop)(self); *self = _cx_memb(_init)(); } \ STC_INLINE void _cx_memb(_swap)(_cx_self* a, _cx_self* b) {c_swap(_cx_self, *a, *b); } \ STC_INLINE _cx_self _cx_memb(_clone)(_cx_self cx) { return c_make(_cx_self){ _cx_memb(_clone_r_)(cx.root), cx.size}; } \ STC_INLINE _cx_iter _cx_memb(_find)(const _cx_self* self, i_keyraw rkey) \ @@ -103,9 +103,9 @@ int main(void) { {_cx_iter it; return _cx_memb(_find_it)(self, rkey, &it); } \ \ STC_INLINE void \ - _cx_memb(_value_del)(_cx_value* val) { \ - i_keydel(_i_keyref(val)); \ - _i_MAP_ONLY( i_valdel(&val->second); ) \ + _cx_memb(_value_drop)(_cx_value* val) { \ + i_keydrop(_i_keyref(val)); \ + _i_MAP_ONLY( i_valdrop(&val->second); ) \ } \ \ STC_INLINE void \ @@ -134,7 +134,7 @@ int main(void) { _cx_memb(_insert)(_cx_self* self, i_key key _i_MAP_ONLY(, i_val mapped)) { \ _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto(&key)); \ if (res.inserted) {*_i_keyref(res.ref) = key; _i_MAP_ONLY( res.ref->second = mapped; )} \ - else {i_keydel(&key); _i_MAP_ONLY( i_valdel(&mapped); )} \ + else {i_keydrop(&key); _i_MAP_ONLY( i_valdrop(&mapped); )} \ return res; \ } \ \ @@ -143,7 +143,7 @@ int main(void) { _cx_memb(_insert_or_assign)(_cx_self* self, i_key key, i_val mapped) { \ _cx_result res = _cx_memb(_insert_entry_)(self, i_keyto(&key)); \ if (res.inserted) res.ref->first = key; \ - else {i_keydel(&key); i_valdel(&res.ref->second); } \ + else {i_keydrop(&key); i_valdrop(&res.ref->second); } \ res.ref->second = mapped; return res; \ } \ \ @@ -156,7 +156,7 @@ int main(void) { _cx_memb(_emplace_or_assign)(_cx_self* self, i_keyraw rkey, i_valraw rmapped) { \ _cx_result res = _cx_memb(_insert_entry_)(self, rkey); \ if (res.inserted) res.ref->first = i_keyfrom(rkey); \ - else i_valdel(&res.ref->second); \ + else i_valdrop(&res.ref->second); \ res.ref->second = i_valfrom(rmapped); return res; \ } \ \ @@ -191,8 +191,8 @@ int main(void) { } \ \ _c_implement_aatree(_cx_self, C, i_key, i_val, i_cmp, \ - i_valdel, i_valfrom, i_valto, i_valraw, \ - i_keydel, i_keyfrom, i_keyto, i_keyraw) \ + i_valdrop, i_valfrom, i_valto, i_valraw, \ + i_keydrop, i_keyfrom, i_keyto, i_keyraw) \ struct stc_trailing_semicolon /* -------------------------- IMPLEMENTATION ------------------------- */ @@ -204,8 +204,8 @@ _c_aatree_complete_types(csmap_SENTINEL, csmap_); static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_sentinel, 0}; #define _c_implement_aatree(_cx_self, C, i_key, i_val, i_cmp, \ - i_valdel, i_valfrom, i_valto, i_valraw, \ - i_keydel, i_keyfrom, i_keyto, i_keyraw) \ + i_valdrop, i_valfrom, i_valto, i_valraw, \ + i_keydrop, i_keyfrom, i_keyto, i_keyraw) \ STC_DEF _cx_self \ _cx_memb(_init)(void) { \ _cx_self cx = {(_cx_node *) &_aatree_sentinel, 0}; \ @@ -330,7 +330,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti if (c != 0) \ tn->link[c < 0] = _cx_memb(_erase_r_)(tn->link[c < 0], rkey, erased); \ else { \ - if (!*erased) { _cx_memb(_value_del)(&tn->value); *erased = 1; } \ + if (!*erased) { _cx_memb(_value_drop)(&tn->value); *erased = 1; } \ if (tn->link[0]->level && tn->link[1]->level) { \ tx = tn->link[0]; \ while (tx->link[1]->level) \ @@ -395,7 +395,7 @@ static csmap_SENTINEL_node _aatree_sentinel = {&_aatree_sentinel, &_aatree_senti if (tn->level != 0) { \ _cx_memb(_del_r_)(tn->link[0]); \ _cx_memb(_del_r_)(tn->link[1]); \ - _cx_memb(_value_del)(&tn->value); \ + _cx_memb(_value_drop)(&tn->value); \ c_free(tn); \ } \ } diff --git a/include/stc/alt/cstr.h b/include/stc/alt/cstr.h index 76b3a800..bd135b7e 100644 --- a/include/stc/alt/cstr.h +++ b/include/stc/alt/cstr.h @@ -41,7 +41,7 @@ typedef union { /**************************** PRIVATE API **********************************/ -enum { SSO_CAP = offsetof(cstr, lon.ncap) + sizeof((cstr){{0}}.lon.ncap) - 1 }; +enum { SSO_CAP = sizeof(_cstr_rep_t) - 1 }; #define cstr_is_long(s) (bool)((s)->sso.cap_len & 128) #define cstr_select_(s, memb) (cstr_is_long(s) ? cstr_l_##memb : cstr_s_##memb) @@ -52,18 +52,18 @@ enum { SSO_CAP = offsetof(cstr, lon.ncap) + sizeof((cstr){{0}}.lon.ncap) - 1 }; #define cstr_s_end(s) ((s)->sso.data + cstr_s_size(s)) #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define byte_rotl_(x, b) ((x) << (b)*8 | (x) >> (sizeof(x) - (b))*8) -#define cstr_l_cap(s) (~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) -#define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_(cap, 1)) + #define byte_rotl_(x, b) ((x) << (b)*8 | (x) >> (sizeof(x) - (b))*8) + #define cstr_l_cap(s) (~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) + #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_(cap, 1)) #else -#define cstr_l_cap(s) (~(s)->lon.ncap) -#define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(cap)) + #define cstr_l_cap(s) (~(s)->lon.ncap) + #define cstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(cap)) #endif #define cstr_l_size(s) ((s)->lon.size) #define cstr_l_set_size(s, len) ((s)->lon.data[(s)->lon.size = (len)] = 0) #define cstr_l_data(s) (s)->lon.data #define cstr_l_end(s) ((s)->lon.data + cstr_l_size(s)) -#define cstr_l_del(s) free((s)->lon.data) +#define cstr_l_drop(s) free((s)->lon.data) STC_API char* cstr_init_(cstr* self, size_t len, size_t cap); STC_API void cstr_internal_move_(cstr* self, size_t pos1, size_t pos2); @@ -74,15 +74,16 @@ STC_INLINE void cstr_set_size_(cstr* self, size_t len) { STC_INLINE _cstr_rep_t cstr_rep_(cstr* self) { return cstr_is_long(self) - ? c_make(_cstr_rep_t){self->lon.data, cstr_l_size(self), cstr_l_cap(self)} - : c_make(_cstr_rep_t){self->sso.data, cstr_s_size(self), cstr_s_cap(self)}; + ? c_make(_cstr_rep_t){self->lon.data, cstr_l_size(self), cstr_l_cap(self)} + : c_make(_cstr_rep_t){self->sso.data, cstr_s_size(self), cstr_s_cap(self)}; } /**************************** PUBLIC API **********************************/ #define cstr_new(literal) cstr_from_n(literal, sizeof((c_strlit){literal}) - 1) #define cstr_npos (SIZE_MAX >> 1) -#define cstr_null (cstr){.sso = {.cap_len = SSO_CAP}} +#define cstr_null (c_make(cstr){.sso = {.cap_len = SSO_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); @@ -126,8 +127,8 @@ STC_INLINE cstr cstr_clone(cstr s) { return cstr_from_n(rep.data, rep.size); } -STC_INLINE void cstr_del(cstr* self) { - if (cstr_is_long(self)) cstr_l_del(self); +STC_INLINE void cstr_drop(cstr* self) { + if (cstr_is_long(self)) cstr_l_drop(self); } STC_INLINE void cstr_clear(cstr* self) { @@ -170,7 +171,7 @@ STC_INLINE bool cstr_equalto(const cstr* s1, const cstr* s2) { return strcmp(cstr_str(s1), cstr_str(s2)) == 0; } -STC_INLINE int cstr_compare(const cstr* s1, const cstr* s2) { +STC_INLINE int cstr_cmp(const cstr* s1, const cstr* s2) { return strcmp(cstr_str(s1), cstr_str(s2)); } diff --git a/include/stc/alt/sstr.h b/include/stc/alt/sstr.h deleted file mode 100644 index 2ea1033d..00000000 --- a/include/stc/alt/sstr.h +++ /dev/null @@ -1,406 +0,0 @@ -/* MIT License - * - * Copyright (c) 2021 Tyge Løvset, NORCE, www.norceresearch.no - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* A string type with short string optimization in C99 with optimal short string - * utilization (23 characters with 24 bytes string representation). - */ -#ifndef SSTR_INCLUDED -#define SSTR_INCLUDED - -#include -#include -#include -#include - -#ifndef sstr_size_t -typedef size_t sstr_size_t; -#endif -typedef struct { char* data; sstr_size_t size, cap; } sstr_rep_t; -typedef const char sstr_literal_t[]; - -typedef union { - struct { char* data; sstr_size_t size, ncap; } lon; - struct { char data[sizeof(sstr_rep_t)]; } sso; -} sstr; - -/**************************** PRIVATE API **********************************/ - -enum { SSO_CAP = offsetof(sstr, lon.ncap) + sizeof((sstr){{0}}.lon.ncap) - 1 }; -#define sstr_is_long(s) (bool)((s)->sso.data[SSO_CAP] & 128) -#define sstr_select_(s, memb) (sstr_is_long(s) ? sstr_l_##memb : sstr_s_##memb) - -#define sstr_s_cap(s) SSO_CAP -#define sstr_s_size(s) ((sstr_size_t)(SSO_CAP - (s)->sso.data[SSO_CAP])) -#define sstr_s_set_size(s, len) ((s)->sso.data[SSO_CAP] = SSO_CAP - (len), (s)->sso.data[len] = 0) -#define sstr_s_data(s) (s)->sso.data -#define sstr_s_end(s) ((s)->sso.data + sstr_s_size(s)) - -#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define byte_rotl_(x, b) ((x) << (b)*8 | (x) >> (sizeof(x) - (b))*8) -#define sstr_l_cap(s) (~byte_rotl_((s)->lon.ncap, sizeof((s)->lon.ncap) - 1)) -#define sstr_l_set_cap(s, cap) ((s)->lon.ncap = ~byte_rotl_(cap, 1)) -#else -#define sstr_l_cap(s) (~(s)->lon.ncap) -#define sstr_l_set_cap(s, cap) ((s)->lon.ncap = ~(cap)) -#endif -#define sstr_l_size(s) ((s)->lon.size) -#define sstr_l_set_size(s, len) ((s)->lon.data[(s)->lon.size = (len)] = 0) -#define sstr_l_data(s) (s)->lon.data -#define sstr_l_end(s) ((s)->lon.data + sstr_l_size(s)) -#define sstr_l_del(s) free((s)->lon.data) - -STC_API char* sstr_init_(sstr* self, sstr_size_t len, sstr_size_t cap); -STC_API void sstr_internal_move_(sstr* self, size_t pos1, size_t pos2); - -STC_INLINE void sstr_set_size_(sstr* self, sstr_size_t len) { - sstr_select_(self, set_size(self, len)); -} - -STC_INLINE sstr_rep_t sstr_rep_(sstr* self) { - return sstr_is_long(self) - ? c_make(sstr_rep_t){self->lon.data, sstr_l_size(self), sstr_l_cap(self)} - : c_make(sstr_rep_t){self->sso.data, sstr_s_size(self), sstr_s_cap(self)}; -} - -/**************************** PUBLIC API **********************************/ - -#define sstr_lit(lit) sstr_from_n(lit, sizeof((sstr_literal_t){lit}) - 1) -#define sstr_npos (~(sstr_size_t)0 >> 1) - -STC_API char* sstr_reserve(sstr* self, sstr_size_t cap); -STC_API void sstr_shrink_to_fit(sstr* self); -STC_API void sstr_resize(sstr* self, sstr_size_t size, char value); -STC_API char* strnstrn(const char *s, const char *needle, size_t slen, size_t nlen); -STC_API sstr_size_t sstr_find_n(sstr s, const char* needle, sstr_size_t pos, sstr_size_t nmax); -STC_API void sstr_assign_n(sstr* self, const char* str, sstr_size_t n); -STC_API void sstr_append_n(sstr* self, const char* str, sstr_size_t n); -STC_API bool sstr_getdelim(sstr *self, int delim, FILE *fp); -STC_API void sstr_erase_n(sstr* self, size_t pos, size_t n); - - -STC_INLINE sstr sstr_init(void) { - sstr s; - sstr_s_set_size(&s, 0); - return s; -} - -STC_INLINE sstr sstr_from_n(const char* str, sstr_size_t n) { - sstr s; - memcpy(sstr_init_(&s, n, n), str, n); - return s; -} - -STC_INLINE sstr sstr_from(const char* str) { - return sstr_from_n(str, strlen(str)); -} - -STC_INLINE sstr sstr_with_size(sstr_size_t size, char value) { - sstr s; - memset(sstr_init_(&s, size, size), value, size); - return s; -} - -STC_INLINE sstr sstr_with_capacity(sstr_size_t cap) { - sstr s; - sstr_init_(&s, 0, cap); - return s; -} - -STC_INLINE sstr sstr_clone(sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - return sstr_from_n(rep.data, rep.size); -} - -STC_INLINE void sstr_del(sstr* self) { - if (sstr_is_long(self)) sstr_l_del(self); -} - -STC_INLINE void sstr_clear(sstr* self) { - sstr_set_size_(self, 0); -} - -STC_INLINE char* sstr_data(sstr* self) { - return sstr_select_(self, data(self)); -} - -STC_INLINE const char* sstr_str(const sstr* self) { - return sstr_select_(self, data(self)); -} - -STC_INLINE bool sstr_empty(sstr s) { - return sstr_select_(&s, size(&s)) == 0; -} - -STC_INLINE sstr_size_t sstr_size(sstr s) { - return sstr_select_(&s, size(&s)); -} - -STC_INLINE sstr_size_t sstr_length(sstr s) { - return sstr_select_(&s, size(&s)); -} - -STC_INLINE sstr_size_t sstr_capacity(sstr s) { - return sstr_select_(&s, cap(&s)); -} - -STC_INLINE bool sstr_equals(sstr s1, const char* str) { - return strcmp(sstr_str(&s1), str) == 0; -} - -STC_INLINE bool sstr_equals_s(sstr s1, sstr s2) { - return strcmp(sstr_str(&s1), sstr_str(&s2)) == 0; -} - -STC_INLINE bool sstr_equalto(const sstr* s1, const sstr* s2) { - return strcmp(sstr_str(s1), sstr_str(s2)) == 0; -} - -STC_INLINE int sstr_compare(const sstr* s1, const sstr* s2) { - return strcmp(sstr_str(s1), sstr_str(s2)); -} - -STC_INLINE sstr_size_t sstr_find(sstr s, const char* needle) { - const char *str = sstr_str(&s), *res = strstr(str, needle); - return res ? res - str : sstr_npos; -} - -STC_INLINE bool sstr_find_s(sstr s, sstr needle) { - return sstr_find(s, sstr_str(&needle)); -} - -STC_INLINE bool sstr_contains(sstr s, const char* needle) { - return strstr(sstr_str(&s), needle) != NULL; -} - -STC_INLINE bool sstr_contains_s(sstr s, sstr needle) { - return strstr(sstr_str(&s), sstr_str(&needle)) != NULL; -} - -STC_INLINE bool sstr_starts_with(sstr s, const char* sub) { - const char* str = sstr_str(&s); - while (*sub && *str == *sub) ++str, ++sub; - return *sub == 0; -} - -STC_INLINE bool sstr_starts_with_s(sstr s, sstr sub) { - return sstr_starts_with(s, sstr_str(&sub)); -} - -STC_INLINE bool sstr_ends_with(sstr s, const char* sub) { - sstr_rep_t rep = sstr_rep_(&s); sstr_size_t n = strlen(sub); - return n <= rep.size && memcmp(rep.data + rep.size - n, sub, n) == 0; -} - -STC_INLINE bool sstr_ends_with_s(sstr s, sstr sub) { - return sstr_ends_with(s, sstr_str(&sub)); -} - -STC_INLINE void sstr_assign(sstr* self, const char* str) { - sstr_assign_n(self, str, strlen(str)); -} - -STC_INLINE void sstr_copy(sstr* self, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_assign_n(self, rep.data, rep.size); -} - -STC_INLINE void sstr_append(sstr* self, const char* str) { - sstr_append_n(self, str, strlen(str)); -} - -STC_INLINE void sstr_append_s(sstr* self, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_append_n(self, rep.data, rep.size); -} - -STC_INLINE void sstr_replace_n(sstr* self, size_t pos, size_t len, const char* str, size_t n) { - sstr_internal_move_(self, pos + len, pos + n); - memcpy(&sstr_data(self)[pos], str, n); -} - -STC_INLINE void sstr_replace(sstr* self, size_t pos, size_t len, const char* str) { - sstr_replace_n(self, pos, len, str, strlen(str)); -} - -STC_INLINE void sstr_replace_s(sstr* self, size_t pos, size_t len, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_replace_n(self, pos, len, rep.data, rep.size); -} - -STC_INLINE void sstr_insert_n(sstr* self, size_t pos, const char* str, size_t n) { - sstr_replace_n(self, pos, 0, str, n); -} - -STC_INLINE void sstr_insert(sstr* self, size_t pos, const char* str) { - sstr_replace_n(self, pos, 0, str, strlen(str)); -} - -STC_INLINE void sstr_insert_s(sstr* self, size_t pos, sstr s) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_replace_n(self, pos, 0, rep.data, rep.size); -} - -STC_INLINE bool sstr_getline(sstr *self, FILE *fp) { - return sstr_getdelim(self, '\n', fp); -} - -/* -------------------------- IMPLEMENTATION ------------------------- */ - -#if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) - -STC_DEF void sstr_internal_move_(sstr* self, size_t pos1, size_t pos2) { - if (pos1 == pos2) - return; - sstr_rep_t rep = sstr_rep_(self); - sstr_size_t newlen = rep.size + pos2 - pos1; - if (newlen > rep.cap) - rep.data = sstr_reserve(self, (rep.size*3 >> 1) + pos2 - pos1); - memmove(&rep.data[pos2], &rep.data[pos1], rep.size - pos1); - sstr_set_size_(self, newlen); -} - -STC_DEF char* sstr_init_(sstr* self, sstr_size_t len, sstr_size_t cap) { - if (cap > SSO_CAP) { - self->lon.data = (char *)malloc(cap + 1); - sstr_l_set_size(self, len); - sstr_l_set_cap(self, cap); - return self->lon.data; - } - sstr_s_set_size(self, len); - return self->sso.data; -} - -STC_DEF void sstr_shrink_to_fit(sstr* self) { - sstr_rep_t rep = sstr_rep_(self); - if (rep.size == rep.cap) - return; - if (rep.size > SSO_CAP) { - self->lon.data = (char *)realloc(self->lon.data, sstr_l_size(self) + 1); - sstr_l_set_cap(self, sstr_l_size(self)); - } else if (rep.cap > SSO_CAP) { - memcpy(self->sso.data, rep.data, rep.size + 1); - sstr_s_set_size(self, rep.size); - free(rep.data); - } -} - -STC_DEF char* sstr_reserve(sstr* self, sstr_size_t cap) { - if (sstr_is_long(self)) { - if (cap > sstr_l_cap(self)) { - self->lon.data = (char *)realloc(self->lon.data, cap + 1); - sstr_l_set_cap(self, cap); - } - return self->lon.data; - } - /* from short to long: */ - if (cap > sstr_s_cap(self)) { - char* data = (char *)malloc(cap + 1); - sstr_size_t len = sstr_s_size(self); - memcpy(data, self->sso.data, len); - self->lon.data = data; - sstr_l_set_size(self, len); - sstr_l_set_cap(self, cap); - return data; - } - return self->sso.data; -} - -STC_DEF void sstr_resize(sstr* self, sstr_size_t size, char value) { - sstr_rep_t rep = sstr_rep_(self); - if (size > rep.size) { - if (size > rep.cap) rep.data = sstr_reserve(self, size); - memset(rep.data + rep.size, value, size - rep.size); - } - sstr_set_size_(self, size); -} - -STC_DEF char* 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, nlen)) return (char *)s; - ++s; - } while (slen--); - return NULL; -} - -STC_DEF sstr_size_t -sstr_find_n(sstr s, const char* needle, sstr_size_t pos, sstr_size_t nmax) { - sstr_rep_t rep = sstr_rep_(&s); - sstr_size_t nlen = (sstr_size_t) strlen(needle); - if (pos > rep.size) return sstr_npos; - char* res = strnstrn(rep.data + pos, needle, rep.size, nmax < nlen ? nmax : nlen); - return res ? res - rep.data : sstr_npos; -} - -STC_DEF void sstr_assign_n(sstr* self, const char* str, sstr_size_t n) { - sstr_rep_t rep = sstr_rep_(self); - if (n > rep.cap) { - rep.data = (char *)realloc(sstr_is_long(self) ? rep.data : NULL, n + 1); - sstr_l_set_cap(self, n); - } - memmove(rep.data, str, n); - sstr_set_size_(self, n); -} - -STC_DEF void sstr_append_n(sstr* self, const char* str, sstr_size_t n) { - sstr_rep_t rep = sstr_rep_(self); - if (rep.size + n > rep.cap) { - sstr_size_t off = (sstr_size_t)(str - rep.data); /* handle self append */ - rep.data = sstr_reserve(self, (rep.size*3 >> 1) + n); - if (off <= rep.size) str = rep.data + off; - } - memcpy(rep.data + rep.size, str, n); - sstr_set_size_(self, rep.size + n); -} - -STC_DEF bool sstr_getdelim(sstr *self, int delim, FILE *fp) { - int c = fgetc(fp); - if (c == EOF) - return false; - sstr_size_t pos = 0; - sstr_rep_t rep = sstr_rep_(self); - for (;;) { - if (c == delim || c == EOF) { - sstr_set_size_(self, pos); - return true; - } - if (pos == rep.cap) { - sstr_set_size_(self, pos); - rep.data = sstr_reserve(self, (rep.cap = (rep.cap*3 >> 1) + 16)); - } - rep.data[pos++] = (char) c; - c = fgetc(fp); - } -} - -STC_DEF void sstr_erase_n(sstr* self, size_t pos, size_t n) { - sstr_rep_t rep = sstr_rep_(self); - if (n > rep.size - pos) n = rep.size - pos; - memmove(&rep.data[pos], &rep.data[pos + n], rep.size - (pos + n)); - sstr_set_size_(self, rep.size - n); -} - -#endif -#endif \ No newline at end of file -- cgit v1.2.3