diff --git a/docs/algorithm_api.md b/docs/algorithm_api.md index e2bf4239..8c41ef66 100644 --- a/docs/algorithm_api.md +++ b/docs/algorithm_api.md @@ -480,27 +480,29 @@ int main(void) {
-c_new, c_delete, c_malloc - Allocation helpers +c_new, c_delete, c_malloc, etc. - Allocation helpers ### c_new, c_delete -- `c_new(Type, val)` - Allocate *and init* a new object on the heap -- `c_delete(Type, ptr)` - Drop *and free* an object allocated on the heap. NULL is OK. +- `c_new(Type, value)` - Allocate *and initialize* a new object on the heap with *value*. +- `c_new_n(Type, n)` - Allocate an array of ***n*** new objects on the heap, initialized to zero. +- `c_delete(Type, ptr)` - *Type_drop(ptr)* and *c_free(ptr, ..)* allocated on the heap. NULL is OK. +- `c_delete_n(Type, arr, n)` - *Type_drop(&arr[i])* and *c_free(arr, ..)* of ***n*** objects allocated on the heap. (NULL, 0) is OK. ```c #include "stc/cstr.h" -cstr *str_p = c_new(cstr, cstr_lit("Hello")); -printf("%s\n", cstr_str(str_p)); -c_delete(cstr, str_p); +cstr* stringptr = c_new (cstr, cstr_from("Hello")); +printf("%s\n", cstr_str(stringp)); +c_delete(cstr, stringptr); ``` ### c_malloc, c_calloc, c_realloc, c_free Memory allocator wrappers which uses signed sizes. Note that the signatures for *c_realloc()* and *c_free()* have an extra size parameter. These will be used as -default unless `i_malloc`, `i_calloc`, `i_realloc`, and `i_free` are defined. See +default in containers unless `i_malloc`, `i_calloc`, `i_realloc`, and `i_free` are user defined. See [Per container-instance customization](../README.md#per-container-instance-customization) - `void* c_malloc(isize sz)` -- `void* c_calloc(isize sz)` +- `void* c_calloc(isize n, isize sz)` - `void* c_realloc(void* old_p, isize old_sz, isize new_sz)` - `void c_free(void* p, isize sz)` diff --git a/docs/cstr_api.md b/docs/cstr_api.md index ce1111c2..d5974c32 100644 --- a/docs/cstr_api.md +++ b/docs/cstr_api.md @@ -26,13 +26,17 @@ cstr cstr_lit(const char literal_only[]); // cstr cstr cstr_init(void); // make an empty string cstr cstr_from(const char* str); // construct from a zero-terminated c-string. cstr cstr_from_s(cstr s, isize pos, isize len); // construct a substring -cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting -cstr cstr_from_replace(csview sv, csview search, csview repl, int32_t count); cstr cstr_from_sv(csview sv); // construct from a string view cstr cstr_from_zv(zsview zv); // construct from a zero-terminated zsview +cstr cstr_from_fmt(const char* fmt, ...); // printf() formatting +cstr cstr_from_replace(csview sv, csview search, csview repl, int32_t count); cstr cstr_with_n(const char* str, isize n); // construct from first n bytes of str cstr cstr_with_capacity(isize cap); // make empty string with pre-allocated capacity. cstr cstr_with_size(isize len, char fill); // make string with fill characters +cstr cstr_join(const char* sep, const char* str1, ...); // construct by joining c-strings with separator +cstr cstr_join_s(const char* sep, cstr s1, ...); // construct by joining cstrs with separator +cstr cstr_join_array(const char* sep, const char* arr[], isize n); // join c-string array with separator +cstr cstr_join_array_s(const char* sep, cstr arr[], isize n); // join cstr array with separator cstr cstr_clone(cstr s); cstr* cstr_take(cstr* self, cstr s); // take ownership of s, i.e. don't drop s. @@ -71,6 +75,7 @@ char* cstr_append_s(cstr* self, cstr str); int cstr_append_fmt(cstr* self, const char* fmt, ...); // printf() formatting char* cstr_append_uninit(cstr* self, isize len); // return ptr to start of uninited data + void cstr_push(cstr* self, const char* chr); // append one utf8 char void cstr_pop(cstr* self); // pop one utf8 char diff --git a/include/stc/common.h b/include/stc/common.h index ae688bac..dba12137 100644 --- a/include/stc/common.h +++ b/include/stc/common.h @@ -72,29 +72,32 @@ typedef ptrdiff_t isize; #define _c_SEL32(a, b, c) b #define _c_SEL33(a, b, c) c +#define _i_malloc(T, n) ((T*)i_malloc((n)*c_sizeof(T))) +#define _i_calloc(T, n) ((T*)i_calloc((n), c_sizeof(T))) #ifndef __cplusplus - #define _i_malloc(T, n) ((T*)i_malloc((n)*c_sizeof(T))) - #define _i_calloc(T, n) ((T*)i_calloc(n, c_sizeof(T))) #define c_new(T, ...) ((T*)memcpy(malloc(sizeof(T)), ((T[]){__VA_ARGS__}), sizeof(T))) #define c_literal(T) (T) #define c_make_array(T, ...) ((T[])__VA_ARGS__) #define c_make_array2d(T, N, ...) ((T[][N])__VA_ARGS__) #else #include - #define _i_malloc(T, n) static_cast(i_malloc((n)*c_sizeof(T))) - #define _i_calloc(T, n) static_cast(i_calloc(n, c_sizeof(T))) #define c_new(T, ...) new (malloc(sizeof(T))) T(__VA_ARGS__) #define c_literal(T) T template struct _c_Array { T data[M][N]; }; #define c_make_array(T, ...) (_c_Array{{__VA_ARGS__}}.data[0]) #define c_make_array2d(T, N, ...) (_c_Array{__VA_ARGS__}.data) #endif -#define c_new_n(T, n) ((T*)malloc(sizeof(T)*c_i2u_size(n))) -#define c_malloc(sz) malloc(c_i2u_size(sz)) -#define c_calloc(n, sz) calloc(c_i2u_size(n), c_i2u_size(sz)) -#define c_realloc(p, old_sz, sz) realloc(p, c_i2u_size(1 ? (sz) : (old_sz))) -#define c_free(p, sz) do { (void)(sz); free(p); } while(0) -#define c_delete(T, ptr) do { T *_tp = ptr; T##_drop(_tp); free(_tp); } while (0) +#ifndef c_malloc + #define c_malloc(sz) malloc(c_i2u_size(sz)) + #define c_calloc(n, sz) calloc(c_i2u_size(n), c_i2u_size(sz)) + #define c_realloc(ptr, old_sz, sz) realloc(ptr, c_i2u_size(1 ? (sz) : (old_sz))) + #define c_free(ptr, sz) do { (void)(sz); free(ptr); } while(0) +#endif +#define c_new_n(T, n) ((T*)c_calloc(n, c_sizeof(T))) +#define c_delete(T, ptr) do { T* _tp = ptr; T##_drop(_tp); c_free(_tp, c_sizeof(T)); } while (0) +#define c_delete_n(T, ptr, n) do { T* _tp = ptr; isize _n = n, _m = _n; \ + while (_n--) T##_drop((_tp + _n)); \ + c_free(_tp, _m*c_sizeof(T)); } while (0) #define c_static_assert(expr) (1 ? 0 : (int)sizeof(int[(expr) ? 1 : -1])) #if defined STC_NDEBUG || defined NDEBUG diff --git a/include/stc/coroutine.h b/include/stc/coroutine.h index aaa9bc10..ee815939 100644 --- a/include/stc/coroutine.h +++ b/include/stc/coroutine.h @@ -145,17 +145,19 @@ typedef struct { /* ============ ADVANCED, OPTIONAL ============= */ /* - * Iterators for coroutine generators - * A type Gen must be an existing generator typedef struct. Then: + * // Iterators for coroutine generators + * + * typedef struct { // The generator + * ... + * } Gen, Gen_value; * - * typedef Gen Gen_value; * typedef struct { * Gen* ref; * cco_state cco; * ... * } Gen_iter; * - * // the generator coroutine, get the next value: + * // The iterator coroutine, produce the next value: * int Gen_next(Gen_iter* it) { * Gen* g = it->ref; * cco_scope (it) { @@ -167,7 +169,7 @@ typedef struct { * } * } * - * // create coroutine/iter, advance to the first yield: + * // Create coroutine / iter, advance to the first yield: * Gen_iter Gen_begin(Gen* g) { * Gen_iter it = {.ref = g}; * ... diff --git a/include/stc/priv/cstr_prv.h b/include/stc/priv/cstr_prv.h index 5466242f..5dda8fed 100644 --- a/include/stc/priv/cstr_prv.h +++ b/include/stc/priv/cstr_prv.h @@ -60,8 +60,14 @@ extern char* _cstr_internal_move(cstr* self, isize pos1, isize pos2); /**************************** PUBLIC API **********************************/ -#define cstr_init() (c_literal(cstr){0}) -#define cstr_lit(literal) cstr_with_n(literal, c_litstrlen(literal)) +#define cstr_init() (c_literal(cstr){0}) +#define cstr_lit(literal) cstr_with_n(literal, c_litstrlen(literal)) +#define cstr_join(sep, ...) \ + cstr_join_array(sep, c_make_array(const char*, {__VA_ARGS__}), \ + c_NUMARGS(__VA_ARGS__)) +#define cstr_join_s(sep, ...) \ + cstr_join_array_s(sep, c_make_array(cstr, {__VA_ARGS__}), \ + c_NUMARGS(__VA_ARGS__)) extern cstr cstr_from_replace(csview sv, csview search, csview repl, int32_t count); extern cstr cstr_from_fmt(const char* fmt, ...); @@ -71,11 +77,13 @@ extern char* cstr_resize(cstr* self, isize size, char value); extern isize cstr_find_at(const cstr* self, isize pos, const char* search); extern isize cstr_find_sv(const cstr* self, csview search); extern char* cstr_assign_n(cstr* self, const char* str, isize len); +STC_INLINE char* cstr_append(cstr* self, const char* str); +STC_INLINE char* cstr_append_s(cstr* self, cstr s); extern char* cstr_append_n(cstr* self, const char* str, isize len); +extern isize cstr_append_fmt(cstr* self, const char* fmt, ...); extern char* cstr_append_uninit(cstr *self, isize len); extern bool cstr_getdelim(cstr *self, int delim, FILE *fp); extern void cstr_erase(cstr* self, isize pos, isize len); -extern isize cstr_append_fmt(cstr* self, const char* fmt, ...); extern isize cstr_printf(cstr* self, const char* fmt, ...); extern size_t cstr_hash(const cstr *self); extern bool cstr_u8_valid(const cstr* self); @@ -103,6 +111,17 @@ STC_INLINE cstr cstr_with_n(const char* str, const isize len) { STC_INLINE cstr cstr_from(const char* str) { return cstr_with_n(str, c_strlen(str)); } +STC_INLINE cstr cstr_join_array(const char* sep, const char* arr[], isize n) { + cstr s = {0}; const char* _sep = ""; + while (n--) { cstr_append(&s, _sep); cstr_append(&s, *arr++); _sep = sep; } + return s; +} +STC_INLINE cstr cstr_join_array_s(const char* sep, cstr arr[], isize n) { + cstr s = {0}; const char* _sep = ""; + while (n--) { cstr_append(&s, _sep); cstr_append_s(&s, *arr++); _sep = sep; } + return s; +} + STC_INLINE cstr cstr_from_sv(csview sv) { return cstr_with_n(sv.buf, sv.size); } diff --git a/misc/tests/cspan_test.c b/misc/tests/cspan_test.c index 8ab26d3b..0eff3600 100644 --- a/misc/tests/cspan_test.c +++ b/misc/tests/cspan_test.c @@ -20,6 +20,7 @@ TEST(cspan, subdim) { } } + TEST(cspan, slice) { int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; Span2 m1 = cspan_md(array, 3, 4); @@ -43,7 +44,8 @@ TEST(cspan, slice) { EXPECT_EQ(45, sum2); } -#define i_type Stack,int + +#define i_type Stack, int #include "stc/stack.h" TEST(cspan, slice2) { @@ -72,6 +74,7 @@ TEST(cspan, slice2) { } } + TEST(cspan, equality) { Span base = c_init(Span, { 3, 1, 2, 3, 1, @@ -106,7 +109,7 @@ TEST(cspan, equality) { } -#define i_type Tiles,Span3 +#define i_type Tiles, Span3 #include "stc/stack.h" TEST_FIXTURE(cspan_cube) { @@ -115,7 +118,7 @@ TEST_FIXTURE(cspan_cube) { }; TEST_SETUP(cspan_cube, fixt) { - enum {TSIZE=4, CUBE=64, N=CUBE*CUBE*CUBE}; + enum {TSIZE = 4, CUBE = 64, N = CUBE*CUBE*CUBE}; fixt->stack = Stack_init(); fixt->tiles = Tiles_init(); @@ -144,8 +147,8 @@ TEST_TEARDOWN(cspan_cube, fixt) { TEST_F(cspan_cube, slice3, fixt) { - isize n = Stack_size(&fixt->stack); - int64_t sum = 0; + int64 n = Stack_size(&fixt->stack); + int64 sum = 0; // iterate each 3d tile in sequence c_foreach (tile, Tiles, fixt->tiles)