From 0c6b41fd08bac55281ff9ad41b0d052171881651 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 26 Oct 2021 20:46:43 +0200 Subject: Added some examples and updated docs. Removed cvec_X_erase() and cdeq_X_erase() - may be used wrong. Use cvec_X_erase_n() instead. Fixed type-bug in cpque.h (same was in cqueue.h). --- benchmarks/others/carray_v1.h | 215 -------------------- benchmarks/others/old/carray_v1.h | 215 ++++++++++++++++++++ benchmarks/others/old/sstr.h | 406 ++++++++++++++++++++++++++++++++++++++ benchmarks/others/sstr.h | 406 -------------------------------------- docs/cdeq_api.md | 1 - docs/cstack_api.md | 4 + docs/cvec_api.md | 1 - examples/runall.sh | 2 +- examples/sptr_pthread.c | 61 ++++++ examples/unordered_map.c | 64 ++++++ examples/unordered_set.c | 41 ++++ include/stc/cdeq.h | 4 - include/stc/cpque.h | 2 +- include/stc/cvec.h | 5 +- 14 files changed, 794 insertions(+), 633 deletions(-) delete mode 100644 benchmarks/others/carray_v1.h create mode 100644 benchmarks/others/old/carray_v1.h create mode 100644 benchmarks/others/old/sstr.h delete mode 100644 benchmarks/others/sstr.h create mode 100644 examples/sptr_pthread.c create mode 100644 examples/unordered_map.c create mode 100644 examples/unordered_set.c diff --git a/benchmarks/others/carray_v1.h b/benchmarks/others/carray_v1.h deleted file mode 100644 index 65777416..00000000 --- a/benchmarks/others/carray_v1.h +++ /dev/null @@ -1,215 +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. - */ -#ifndef CARRAY_H_INCLUDED -#define CARRAY_H_INCLUDED - -#include -#include "ccommon.h" - -/* - Multi-dimensional generic array allocated as one block of heap-memory. - // demo: -#include -#include "stc/carray.h" -using_carray3(f, float); - -int main() -{ - carray3f a3 = carray3f_init(30, 20, 10, 0.0f); - *carray3f_at(&a3, 5, 4, 3) = 10.2f; // a3[5][4][3] - carray2f a2 = carray3f_at1(&a3, 5); // sub-array reference: a2 = a3[5] - printf("%g\n", *carray2f_at(&a2, 4, 3)); // lookup a2[4][3] (=10.2f) - printf("%g\n", *carray3f_at(&a3, 5, 4, 3)); // same data location, via a3 array. - - carray2f_del(&a2); // does nothing, since it is a sub-array. - carray3f_del(&a3); // destroy a3, invalidates a2. -} -*/ - -#define using_carray2(...) c_MACRO_OVERLOAD(using_carray2, __VA_ARGS__) - -#define using_carray2_2(X, Value) \ - using_carray2_4(X, Value, c_default_del, c_default_fromraw) - -#define using_carray2_4(X, Value, valueDel, valueClone) \ -\ - typedef Value carray1##X##_value_t, carray2##X##_value_t; \ -\ - typedef struct { \ - carray1##X##_value_t *data; \ - size_t _xdim; \ - } carray1##X; \ -\ - typedef struct { \ - carray2##X##_value_t *data; \ - size_t _xdim, _ydim; \ - } carray2##X; \ -\ - STC_INLINE size_t \ - carray1##X##_size(carray1##X a) {return _carray_xdim(a);} \ - STC_INLINE size_t \ - carray2##X##_size(carray2##X a) {return _carray_xdim(a)*_carray_ydim(a);} \ - STC_INLINE size_t \ - carray2##X##_ydim(carray2##X a) {return _carray_ydim(a);} \ -\ - _using_carray_common(1, X, Value, valueDel, valueClone) \ - _using_carray_common(2, X, Value, valueDel, valueClone) \ -\ - STC_INLINE carray1##X \ - carray1##X##_init(size_t xdim, Value val) { \ - carray1##X##_value_t* m = c_new_n(carray1##X##_value_t, xdim); \ - for (size_t i=0; idata + x; } \ - \ - STC_INLINE carray1##X \ - carray2##X##_at1(const carray2##X *a, size_t y) { \ - carray1##X sub = {a->data + y*_carray_xdim(*a), _carray_xdim(*a)}; \ - return sub; \ - } \ - STC_INLINE carray2##X##_value_t* \ - carray2##X##_at(const carray2##X *a, size_t y, size_t x) { \ - return a->data + y*_carray_xdim(*a) + x; \ - } \ - typedef carray2##X carray2##X##_t - - -#define using_carray3(...) c_MACRO_OVERLOAD(using_carray3, __VA_ARGS__) - -#define using_carray3_2(X, Value) \ - using_carray3_4(X, Value, c_default_del, c_default_fromraw) - -#define using_carray3_4(X, Value, valueDel, valueClone) \ -\ - using_carray2_4(X, Value, valueDel, valueClone); \ - typedef Value carray3##X##_value_t; \ -\ - typedef struct { \ - carray3##X##_value_t *data; \ - size_t _xdim, _ydim, _zdim; \ - } carray3##X; \ -\ - STC_INLINE size_t \ - carray3##X##_size(carray3##X a) {return _carray_xdim(a)*_carray_ydim(a)*_carray_zdim(a);} \ - STC_INLINE size_t \ - carray3##X##_ydim(carray3##X a) {return _carray_ydim(a);} \ - STC_INLINE size_t \ - carray3##X##_zdim(carray3##X a) {return _carray_zdim(a);} \ -\ - _using_carray_common(3, X, Value, valueDel, valueClone) \ -\ - STC_INLINE carray3##X \ - carray3##X##_init(size_t zdim, size_t ydim, size_t xdim, Value val) { \ - const size_t n = zdim * ydim * xdim; \ - carray3##X##_value_t* m = c_new_n(carray3##X##_value_t, n); \ - for (size_t i=0; idata + z*_carray_ydim(*a)*_carray_xdim(*a), _carray_xdim(*a), _carray_ydim(*a)}; \ - return sub; \ - } \ - STC_INLINE carray1##X \ - carray3##X##_at2(const carray3##X *a, size_t z, size_t y) { \ - carray1##X sub = {a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a), _carray_xdim(*a)}; \ - return sub; \ - } \ - STC_INLINE carray3##X##_value_t* \ - carray3##X##_at(const carray3##X *a, size_t z, size_t y, size_t x) { \ - return a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a) + x; \ - } \ - typedef carray3##X carray3##X##_t - - -#define _carray_SUB (SIZE_MAX >> 1) -#define _carray_OWN (_carray_SUB + 1) -#define _carray_xdim(a) ((a)._xdim & _carray_SUB) -#define _carray_ydim(a) (a)._ydim -#define _carray_zdim(a) (a)._zdim - -#define _using_carray_common(D, X, Value, valueDel, valueClone) \ - typedef struct { carray1##X##_value_t *ref; } carray##D##X##_iter_t; \ -\ - STC_INLINE carray##D##X##_iter_t \ - carray##D##X##_begin(const carray##D##X* a) { \ - carray##D##X##_iter_t it = {a->data}; return it; \ - } \ - STC_INLINE carray##D##X##_iter_t \ - carray##D##X##_end(const carray##D##X* a) { \ - carray##D##X##_iter_t it = {a->data + carray##D##X##_size(*a)}; return it; \ - } \ - STC_INLINE void \ - carray##D##X##_next(carray##D##X##_iter_t* it) {++it->ref;} \ -\ - STC_INLINE void \ - carray##D##X##_del(carray##D##X* self) { \ - if (self->_xdim & _carray_OWN) { \ - c_foreach_3 (i, carray##D##X, *self) \ - valueDel(i.ref); \ - c_free(self->data); \ - } \ - } \ - STC_INLINE carray##D##X \ - carray##D##X##_clone(carray##D##X arr) { \ - carray##D##X cp = arr; size_t k = 0; \ - cp.data = c_new_n(carray1##X##_value_t, carray##D##X##_size(arr)); \ - c_foreach_3 (i, carray##D##X, arr) \ - cp.data[k++] = valueClone(*i.ref); \ - return cp; \ - } \ - STC_INLINE size_t \ - carray##D##X##_xdim(carray##D##X a) {return _carray_xdim(a);} \ - -#endif diff --git a/benchmarks/others/old/carray_v1.h b/benchmarks/others/old/carray_v1.h new file mode 100644 index 00000000..65777416 --- /dev/null +++ b/benchmarks/others/old/carray_v1.h @@ -0,0 +1,215 @@ +/* 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. + */ +#ifndef CARRAY_H_INCLUDED +#define CARRAY_H_INCLUDED + +#include +#include "ccommon.h" + +/* + Multi-dimensional generic array allocated as one block of heap-memory. + // demo: +#include +#include "stc/carray.h" +using_carray3(f, float); + +int main() +{ + carray3f a3 = carray3f_init(30, 20, 10, 0.0f); + *carray3f_at(&a3, 5, 4, 3) = 10.2f; // a3[5][4][3] + carray2f a2 = carray3f_at1(&a3, 5); // sub-array reference: a2 = a3[5] + printf("%g\n", *carray2f_at(&a2, 4, 3)); // lookup a2[4][3] (=10.2f) + printf("%g\n", *carray3f_at(&a3, 5, 4, 3)); // same data location, via a3 array. + + carray2f_del(&a2); // does nothing, since it is a sub-array. + carray3f_del(&a3); // destroy a3, invalidates a2. +} +*/ + +#define using_carray2(...) c_MACRO_OVERLOAD(using_carray2, __VA_ARGS__) + +#define using_carray2_2(X, Value) \ + using_carray2_4(X, Value, c_default_del, c_default_fromraw) + +#define using_carray2_4(X, Value, valueDel, valueClone) \ +\ + typedef Value carray1##X##_value_t, carray2##X##_value_t; \ +\ + typedef struct { \ + carray1##X##_value_t *data; \ + size_t _xdim; \ + } carray1##X; \ +\ + typedef struct { \ + carray2##X##_value_t *data; \ + size_t _xdim, _ydim; \ + } carray2##X; \ +\ + STC_INLINE size_t \ + carray1##X##_size(carray1##X a) {return _carray_xdim(a);} \ + STC_INLINE size_t \ + carray2##X##_size(carray2##X a) {return _carray_xdim(a)*_carray_ydim(a);} \ + STC_INLINE size_t \ + carray2##X##_ydim(carray2##X a) {return _carray_ydim(a);} \ +\ + _using_carray_common(1, X, Value, valueDel, valueClone) \ + _using_carray_common(2, X, Value, valueDel, valueClone) \ +\ + STC_INLINE carray1##X \ + carray1##X##_init(size_t xdim, Value val) { \ + carray1##X##_value_t* m = c_new_n(carray1##X##_value_t, xdim); \ + for (size_t i=0; idata + x; } \ + \ + STC_INLINE carray1##X \ + carray2##X##_at1(const carray2##X *a, size_t y) { \ + carray1##X sub = {a->data + y*_carray_xdim(*a), _carray_xdim(*a)}; \ + return sub; \ + } \ + STC_INLINE carray2##X##_value_t* \ + carray2##X##_at(const carray2##X *a, size_t y, size_t x) { \ + return a->data + y*_carray_xdim(*a) + x; \ + } \ + typedef carray2##X carray2##X##_t + + +#define using_carray3(...) c_MACRO_OVERLOAD(using_carray3, __VA_ARGS__) + +#define using_carray3_2(X, Value) \ + using_carray3_4(X, Value, c_default_del, c_default_fromraw) + +#define using_carray3_4(X, Value, valueDel, valueClone) \ +\ + using_carray2_4(X, Value, valueDel, valueClone); \ + typedef Value carray3##X##_value_t; \ +\ + typedef struct { \ + carray3##X##_value_t *data; \ + size_t _xdim, _ydim, _zdim; \ + } carray3##X; \ +\ + STC_INLINE size_t \ + carray3##X##_size(carray3##X a) {return _carray_xdim(a)*_carray_ydim(a)*_carray_zdim(a);} \ + STC_INLINE size_t \ + carray3##X##_ydim(carray3##X a) {return _carray_ydim(a);} \ + STC_INLINE size_t \ + carray3##X##_zdim(carray3##X a) {return _carray_zdim(a);} \ +\ + _using_carray_common(3, X, Value, valueDel, valueClone) \ +\ + STC_INLINE carray3##X \ + carray3##X##_init(size_t zdim, size_t ydim, size_t xdim, Value val) { \ + const size_t n = zdim * ydim * xdim; \ + carray3##X##_value_t* m = c_new_n(carray3##X##_value_t, n); \ + for (size_t i=0; idata + z*_carray_ydim(*a)*_carray_xdim(*a), _carray_xdim(*a), _carray_ydim(*a)}; \ + return sub; \ + } \ + STC_INLINE carray1##X \ + carray3##X##_at2(const carray3##X *a, size_t z, size_t y) { \ + carray1##X sub = {a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a), _carray_xdim(*a)}; \ + return sub; \ + } \ + STC_INLINE carray3##X##_value_t* \ + carray3##X##_at(const carray3##X *a, size_t z, size_t y, size_t x) { \ + return a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a) + x; \ + } \ + typedef carray3##X carray3##X##_t + + +#define _carray_SUB (SIZE_MAX >> 1) +#define _carray_OWN (_carray_SUB + 1) +#define _carray_xdim(a) ((a)._xdim & _carray_SUB) +#define _carray_ydim(a) (a)._ydim +#define _carray_zdim(a) (a)._zdim + +#define _using_carray_common(D, X, Value, valueDel, valueClone) \ + typedef struct { carray1##X##_value_t *ref; } carray##D##X##_iter_t; \ +\ + STC_INLINE carray##D##X##_iter_t \ + carray##D##X##_begin(const carray##D##X* a) { \ + carray##D##X##_iter_t it = {a->data}; return it; \ + } \ + STC_INLINE carray##D##X##_iter_t \ + carray##D##X##_end(const carray##D##X* a) { \ + carray##D##X##_iter_t it = {a->data + carray##D##X##_size(*a)}; return it; \ + } \ + STC_INLINE void \ + carray##D##X##_next(carray##D##X##_iter_t* it) {++it->ref;} \ +\ + STC_INLINE void \ + carray##D##X##_del(carray##D##X* self) { \ + if (self->_xdim & _carray_OWN) { \ + c_foreach_3 (i, carray##D##X, *self) \ + valueDel(i.ref); \ + c_free(self->data); \ + } \ + } \ + STC_INLINE carray##D##X \ + carray##D##X##_clone(carray##D##X arr) { \ + carray##D##X cp = arr; size_t k = 0; \ + cp.data = c_new_n(carray1##X##_value_t, carray##D##X##_size(arr)); \ + c_foreach_3 (i, carray##D##X, arr) \ + cp.data[k++] = valueClone(*i.ref); \ + return cp; \ + } \ + STC_INLINE size_t \ + carray##D##X##_xdim(carray##D##X a) {return _carray_xdim(a);} \ + +#endif diff --git a/benchmarks/others/old/sstr.h b/benchmarks/others/old/sstr.h new file mode 100644 index 00000000..5301978a --- /dev/null +++ b/benchmarks/others/old/sstr.h @@ -0,0 +1,406 @@ +/* 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_equalto(sstr s1, const char* str) { + return strcmp(sstr_str(&s1), str) == 0; +} + +STC_INLINE bool sstr_equalto_s(sstr s1, sstr s2) { + return strcmp(sstr_str(&s1), sstr_str(&s2)) == 0; +} + +STC_INLINE int sstr_equals(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*13 >> 3) + 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*13 >> 3) + 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*13 >> 3) + 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 diff --git a/benchmarks/others/sstr.h b/benchmarks/others/sstr.h deleted file mode 100644 index 5301978a..00000000 --- a/benchmarks/others/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_equalto(sstr s1, const char* str) { - return strcmp(sstr_str(&s1), str) == 0; -} - -STC_INLINE bool sstr_equalto_s(sstr s1, sstr s2) { - return strcmp(sstr_str(&s1), sstr_str(&s2)) == 0; -} - -STC_INLINE int sstr_equals(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*13 >> 3) + 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*13 >> 3) + 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*13 >> 3) + 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 diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index 90a44293..4f188143 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -62,7 +62,6 @@ cdeq_X_iter_t cdeq_X_emplace_range(cdeq_X* self, cdeq_X_iter_t it, cdeq_X_iter_t cdeq_X_emplace_range_p(cdeq_X* self, i_val* pos, const i_val* p1, const i_val* p2); -cdeq_X_iter_t cdeq_X_erase(cdeq_X* self, size_t idx); cdeq_X_iter_t cdeq_X_erase_n(cdeq_X* self, size_t idx, size_t n); cdeq_X_iter_t cdeq_X_erase_at(cdeq_X* self, cdeq_X_iter_t it); cdeq_X_iter_t cdeq_X_erase_range(cdeq_X* self, cdeq_X_iter_t it1, cdeq_X_iter_t it2); diff --git a/docs/cstack_api.md b/docs/cstack_api.md index 5b878ba4..c4a806e1 100644 --- a/docs/cstack_api.md +++ b/docs/cstack_api.md @@ -23,6 +23,8 @@ See the c++ class [std::stack](https://en.cppreference.com/w/cpp/container/stack ```c cstack_X cstack_X_init(void); +cstack_X cstack_with_capacity(size_t cap); +cstack_X cstack_with_size(size_t size, i_val fill); cstack_X cstack_X_clone(cstack_X st); void cstack_X_clear(cstack_X* self); @@ -32,8 +34,10 @@ void cstack_X_copy(cstack_X* self, cstack_X other); void cstack_X_del(cstack_X* self); // destructor size_t cstack_X_size(cstack_X st); +size_t cstack_X_capacity(cstack_X st); bool cstack_X_empty(cstack_X st); cstack_X_value_t* cstack_X_top(const cstack_X* self); +cstack_X_value_t* cstack_X_at(const cstack_X* self, size_t idx); cstack_X_value_t* cstack_X_push(cstack_X* self, i_val value); cstack_X_value_t* cstack_X_emplace(cstack_X* self, i_valraw raw); diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 3a78bf58..a14f6952 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -65,7 +65,6 @@ cvec_X_iter_t cvec_X_emplace_range(cvec_X* self, cvec_X_iter_t it, cvec_X_iter_t cvec_X_emplace_range_p(cvec_X* self, i_val* pos, const i_val* p1, const i_val* p2); -cvec_X_iter_t cvec_X_erase(cvec_X* self, size_t idx); cvec_X_iter_t cvec_X_erase_n(cvec_X* self, size_t idx, size_t n); cvec_X_iter_t cvec_X_erase_at(cvec_X* self, cvec_X_iter_t it); cvec_X_iter_t cvec_X_erase_range(cvec_X* self, cvec_X_iter_t it1, cvec_X_iter_t it2); diff --git a/examples/runall.sh b/examples/runall.sh index cec626a6..12c72684 100644 --- a/examples/runall.sh +++ b/examples/runall.sh @@ -8,7 +8,7 @@ cc='gcc -std=c99 -pedantic' libs='' run=0 if [ -z "$OS" ]; then - libs='-lm' + libs='-lm -pthread' fi if [ "$1" == '-h' -o "$1" == '--help' ]; then echo usage: runall.sh [-run] [compiler + options] diff --git a/examples/sptr_pthread.c b/examples/sptr_pthread.c new file mode 100644 index 00000000..8957a118 --- /dev/null +++ b/examples/sptr_pthread.c @@ -0,0 +1,61 @@ +// example based on https://en.cppreference.com/w/cpp/memory/shared_ptr +#if defined __GNUC__ || defined __linux__ + +#include +#include +#include +#include + +struct Base +{ + int value; +} typedef Base; + +void Base_del(Base* b) { printf("Base::~Base()\n"); } + +#define i_val Base +#define i_cmp c_no_compare +#define i_del Base_del +#define i_tag base +#include + +void* thr(csptr_base* lp) +{ + static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; + sleep(1); + c_autoscope (pthread_mutex_lock(&mtx), pthread_mutex_unlock(&mtx)) + { + printf("local pointer in a thread:\n" + " p.get() = %p, p.use_count() = %zu\n", lp->get, *lp->use_count); + } + /* atomically decrease ref. */ + csptr_base_del(lp); + return NULL; +} + +int main() +{ + csptr_base p = csptr_base_make((Base){42}); + + printf("Created a Base\n" + " p.get() = %p, p.use_count() = %zu\n", p.get, *p.use_count); + enum {N = 3}; + pthread_t t[N]; + csptr_base c[N]; + c_forrange (i, N) { + c[i] = csptr_base_clone(p); + pthread_create(&t[i], NULL, (void*(*)(void*))thr, &c[i]); + } + + printf("Shared ownership between %d threads and released\n" + "ownership from main:\n" + " p.get() = %p, p.use_count() = %zu\n", N, p.get, *p.use_count); + csptr_base_reset(&p); + + c_forrange (i, N) pthread_join(t[i], NULL); + printf("All threads completed, the last one deleted Base\n"); +} + +#else +int main() {} +#endif \ No newline at end of file diff --git a/examples/unordered_map.c b/examples/unordered_map.c new file mode 100644 index 00000000..7af6fa0a --- /dev/null +++ b/examples/unordered_map.c @@ -0,0 +1,64 @@ +// https://iq.opengenus.org/containers-cpp-stl/ + +#define i_key int +#define i_val int +#include +#include + +int main() +{ + + // empty map containers + c_auto (csmap_int, gquiz1, gquiz2) + { + // insert elements in random order + csmap_int_insert(&gquiz1, 2, 30); + csmap_int_insert(&gquiz1, 4, 20); + csmap_int_insert(&gquiz1, 7, 10); + csmap_int_insert(&gquiz1, 5, 50); + csmap_int_insert(&gquiz1, 3, 60); + csmap_int_insert(&gquiz1, 1, 40); + csmap_int_insert(&gquiz1, 6, 50); + + // printing map gquiz1 + printf("\nThe map gquiz1 is :\n\tKEY\tELEMENT\n"); + c_foreach (itr, csmap_int, gquiz1) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // assigning the elements from gquiz1 to gquiz2 + c_foreach (i, csmap_int, gquiz1) + csmap_int_insert(&gquiz2, i.ref->first, i.ref->second); + + // print all elements of the map gquiz2 + printf("\nThe map gquiz2 is :\n\tKEY\tELEMENT\n"); + c_foreach (itr, csmap_int, gquiz2) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // remove all elements up to element with key=3 in gquiz2 + printf("\ngquiz2 after removal of elements less than key=3 :\n"); + printf("\tKEY\tELEMENT\n"); + csmap_int_erase_range(&gquiz2, csmap_int_begin(&gquiz2), + csmap_int_find(&gquiz2, 3)); + c_foreach (itr, csmap_int, gquiz2) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // remove all elements with key = 4 + int num = csmap_int_erase(&gquiz2, 4); + printf("\ngquiz2.erase(4) : %d removed\n", num); + printf("\tKEY\tELEMENT\n"); + c_foreach (itr, csmap_int, gquiz2) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // lower bound and upper bound for map gquiz1 key = 5 + printf("gquiz1.lower_bound(5) : "); + printf("\tKEY = %d\t", csmap_int_lower_bound(&gquiz1, 5).ref->first); + printf("\tELEMENT = %d\n", csmap_int_lower_bound(&gquiz1, 5).ref->second); + printf("gquiz1.upper_bound(5) : "); + printf("\tKEY = %d\t", csmap_int_lower_bound(&gquiz1, 5+1).ref->first); + printf("\tELEMENT = %d\n", csmap_int_lower_bound(&gquiz1, 5+1).ref->second); + } +} diff --git a/examples/unordered_set.c b/examples/unordered_set.c new file mode 100644 index 00000000..f4e37cf8 --- /dev/null +++ b/examples/unordered_set.c @@ -0,0 +1,41 @@ +// https://iq.opengenus.org/containers-cpp-stl/ +// C program to demonstrate various function of stc cset +#define i_key_str +#include + +int main() +{ + // declaring set for storing string data-type + c_auto (cset_str, stringSet) + { + // inserting various string, same string will be stored + // once in set + cset_str_emplace(&stringSet, "code"); + cset_str_emplace(&stringSet, "in"); + cset_str_emplace(&stringSet, "C"); + cset_str_emplace(&stringSet, "is"); + cset_str_emplace(&stringSet, "fast"); + + const char* key = "slow"; + + // find returns end iterator if key is not found, + // else it returns iterator to that key + + if (cset_str_find(&stringSet, key).ref == cset_str_end(&stringSet).ref) + printf("\"%s\" not found\n", key); + else + printf("Found \"%s\"\n", key); + + key = "C"; + if (!cset_str_contains(&stringSet, key)) + printf("\"%s\" not found\n", key); + else + printf("Found \"%s\"\n", key); + + // now iterating over whole set and printing its + // content + printf("All elements :\n"); + c_foreach (itr, cset_str, stringSet) + printf("%s\n", itr.ref->str); + } +} diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h index 264761e0..160c7601 100644 --- a/include/stc/cdeq.h +++ b/include/stc/cdeq.h @@ -157,10 +157,6 @@ cx_memb(_emplace_range)(Self* self, cx_iter_t it, cx_iter_t it1, cx_iter_t it2) return cx_memb(_insert_range_p)(self, it.ref, it1.ref, it2.ref, true); } -STC_INLINE cx_iter_t -cx_memb(_erase)(Self* self, size_t idx) { - return cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + 1); -} STC_INLINE cx_iter_t cx_memb(_erase_n)(Self* self, size_t idx, size_t n) { return cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); diff --git a/include/stc/cpque.h b/include/stc/cpque.h index 0a06fc40..3fc8ebea 100644 --- a/include/stc/cpque.h +++ b/include/stc/cpque.h @@ -53,7 +53,7 @@ STC_INLINE Self cx_memb(_with_capacity)(size_t cap) { STC_INLINE void cx_memb(_reserve)(Self* self, size_t n) { if (n >= self->size) - self->data = (cx_value_t *)c_realloc(self->data, (self->capacity = n)*sizeof(cx_rawvalue_t)); + self->data = (cx_value_t *)c_realloc(self->data, (self->capacity = n)*sizeof(cx_value_t)); } STC_INLINE void cx_memb(_clear)(Self* self) { diff --git a/include/stc/cvec.h b/include/stc/cvec.h index ff5b4399..3810e678 100644 --- a/include/stc/cvec.h +++ b/include/stc/cvec.h @@ -172,10 +172,7 @@ STC_INLINE cx_iter_t cx_memb(_emplace_range)(Self* self, cx_iter_t it, cx_iter_t it1, cx_iter_t it2) { return cx_memb(_insert_range_p)(self, it.ref, it1.ref, it2.ref, true); } -STC_INLINE cx_iter_t -cx_memb(_erase)(Self* self, size_t idx) { - return cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + 1); -} + STC_INLINE cx_iter_t cx_memb(_erase_n)(Self* self, size_t idx, size_t n) { return cx_memb(_erase_range_p)(self, self->data + idx, self->data + idx + n); -- cgit v1.2.3