From 7afd74657220e0fb1fc05e9d0a053cfa2acc767a Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Sat, 2 Jan 2021 20:59:48 +0100 Subject: Major upgrade: Added 'clone' template parameters to containers. Reorganized arg positions. Renamed csptr_X_share() to csptr_X_clone() --- docs/cdeq_api.md | 2 +- docs/clist_api.md | 2 +- docs/cmap_api.md | 18 +++++--- docs/cptr_api.md | 14 +++--- docs/cset_api.md | 6 +-- docs/cvec_api.md | 2 +- examples/advanced.c | 5 ++- examples/complex.c | 42 +++++++++--------- examples/demos.c | 4 +- examples/inits.c | 2 +- examples/ptr.c | 82 ++++++++++++++++++++--------------- examples/share_ptr.c | 6 +-- stc/carray.h | 119 ++++++++++++++++++++++++++++----------------------- stc/cbitset.h | 2 +- stc/ccommon.h | 1 + stc/cdeq.h | 4 +- stc/clist.h | 4 +- stc/cmap.h | 74 ++++++++++++++++++++++---------- stc/cptr.h | 15 +++++-- stc/cstr.h | 2 +- stc/cvec.h | 4 +- 21 files changed, 239 insertions(+), 171 deletions(-) diff --git a/docs/cdeq_api.md b/docs/cdeq_api.md index e30967f1..12fd3958 100644 --- a/docs/cdeq_api.md +++ b/docs/cdeq_api.md @@ -9,7 +9,7 @@ See [std::deque](https://en.cppreference.com/w/cpp/container/deque) for correspo ```c #define using_cdeq(X, Value, valueCompareRaw=c_default_compare, valueDestroy=c_default_del, - valueFromRaw=c_default_from_raw, + valueFromRaw=c_default_clone, valueToRaw=c_default_to_raw, RawValue=Value) #define using_cdeq_str() diff --git a/docs/clist_api.md b/docs/clist_api.md index 10956903..4f5325e7 100644 --- a/docs/clist_api.md +++ b/docs/clist_api.md @@ -11,7 +11,7 @@ is only one pointer, and length of the list is not stored. The method *clist_X_s ```c #define using_clist(X, Value, valueCompareRaw=c_default_compare, valueDestroy=c_default_del, - valueFromRaw=c_default_from_raw, + valueFromRaw=c_default_clone, valueToRaw=c_default_to_raw, RawValue=Value) #define using_clist_str() diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 69c975af..4a696ab7 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -9,23 +9,27 @@ See [std::unordered_map](https://en.cppreference.com/w/cpp/container/unordered_m ```c #define using_cmap(X, Key, Mapped, mappedDestroy=c_default_del, + mappedClone=c_default_clone, keyEqualsRaw=c_default_equals, keyHashRaw=c_default_hash, keyDestroy=c_default_del, - RawKey=Key, - keyFromRaw=c_default_from_raw, + keyFromRaw=c_default_clone, keyToRaw=c_default_to_raw, - RawMapped=Mapped, - mappedFromRaw=c_default_from_raw) + RawKey=Key) +// or: +#define using_cmap(X, Key, Mapped, mappedDestroy, + mappedFromRaw, keyFromRaw, RawMapped, + keyEqualsRaw, keyHashRaw, keyDestroy, + keyFromRaw, keyToRaw, RawKey) #define using_cmap_strkey(X, Mapped, mappedDestroy=c_default_del) #define using_cmap_strval(X, Key, keyEquals=c_default_equals, keyHash=c_default_hash, keyDestroy=c_default_del, - RawKey=Key, - keyFromRaw=c_default_from_raw, - keyToRaw=c_default_to_raw) + keyFromRaw=c_default_clone, + keyToRaw=c_default_to_raw, + RawKey=Key) #define using_cmap_str() ``` The macro `using_cmap()` can be instantiated with 3, 4, 6, 10, or 12 arguments in the global scope. diff --git a/docs/cptr_api.md b/docs/cptr_api.md index fe79d042..0d6a37ba 100644 --- a/docs/cptr_api.md +++ b/docs/cptr_api.md @@ -3,16 +3,18 @@ This module simplifies management of pointers in containers. The **csptr** type is similar to a c++ [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr). -Raw pointers and shared pointers (**csptr**) may be used as items of containers. The pointed-to elements are automatically destructed and deleted when the container is destructed. **csptr** elements are only deleted if there are no other shared references to the element. **csptr** uses thread-safe atomic use-count, through the *csptr_X_share(sp)* and *csptr_X_del(&sp)* methods. +Raw pointers and shared pointers (**csptr**) may be used as items of containers. The pointed-to elements are automatically destructed and deleted when the container is destructed. **csptr** elements are only deleted if there are no other shared references to the element. **csptr** uses thread-safe atomic use-count, through the *csptr_X_clone(sp)* and *csptr_X_del(&sp)* methods. ## Declaration ```c #define using_cptr(X, Value, valueCompare=c_default_compare, - valueDestroy=c_default_del) + valueDestroy=c_default_del, + valueClone=c_default_clone) #define using_csptr(X, Value, valueCompare=c_default_compare, - valueDestroy=c_default_del) + valueDestroy=c_default_del, + valueClone=c_default_clone) ``` The macro `using_cptr()` must be instantiated in the global scope. `X` is a type tag name and will affect the names of all cptr types and methods. E.g. declaring `using_cptr(my, cvec_my);`, @@ -43,7 +45,7 @@ All cptr definitions and prototypes may be included in your C source file by inc ## Methods -The *\*_del()* and *\*_compare()* methods are defined based on the methods passed to the *using_\*ptr()* macro. For *csptr* use *csptr_X_share(p)* when sharing ownership of the pointed-to object to others. See example below. +The *\*_del()* and *\*_compare()* methods are defined based on the methods passed to the *using_\*ptr()* macro. For *csptr* use *csptr_X_clone(p)* when sharing ownership of the pointed-to object to others. See example below. ```c cptr_X cptr_X_init(void); void cptr_X_reset(cptr_X* self, cptr_X_value_t* ptr); @@ -53,7 +55,7 @@ int cptr_X_compare(cptr_X* x, cptr_X* y); ```c csptr_X csptr_X_from(csptr_X_value_t* ptr); csptr_X csptr_X_make(csptr_X_value_t ref); -csptr_X csptr_X_share(csptr_X ptr); +csptr_X csptr_X_clone(csptr_X ptr); void csptr_X_reset(csptr_X* self, csptr_X_value_t* p); void csptr_X_del(csptr_X* self); int csptr_X_compare(csptr_X* x, csptr_X* y); @@ -126,7 +128,7 @@ int main() { printf(" %s %s\n", i.ref->get->name.str, i.ref->get->last.str); // share ownership of vec3.data[1] with elem: - csptr_ps elem = csptr_ps_share(vec3.data[1]); + csptr_ps elem = csptr_ps_clone(vec3.data[1]); puts("\nDestroy vec3:"); cvec_ps_del(&vec3); // destroys all elements, but elem! diff --git a/docs/cset_api.md b/docs/cset_api.md index 99940b03..412ff572 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -11,9 +11,9 @@ A **cset** is an associative container that contains a set of unique objects of #define using_cset(X, Key, keyEqualsRaw=c_default_equals, keyHashRaw=c_default_hash, keyDestroy=c_default_del, - RawKey=Key, - keyToRaw=c_default_to_raw, - keyFromRaw=c_default_from_raw) + keyFromRaw=c_default_clone, + keyToRaw=c_default_to_raw, + RawKey=Key) ``` The macro `using_cset()` can be instantiated with 2, 4, 5, or 8 arguments in the global scope. Default values are given above for args not specified. `X` is a type tag name and diff --git a/docs/cvec_api.md b/docs/cvec_api.md index de437853..afdeef46 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -9,7 +9,7 @@ See [std::vector](https://en.cppreference.com/w/cpp/container/vector) for a simi ```c #define using_cvec(X, Value, valueCompareRaw=c_default_compare, valueDestroy=c_default_del, - valueFromRaw=c_default_from_raw, + valueFromRaw=c_default_clone, valueToRaw=c_default_to_raw, RawValue=Value) #define using_cvec_str() diff --git a/examples/advanced.c b/examples/advanced.c index b3f2f380..bad0346e 100644 --- a/examples/advanced.c +++ b/examples/advanced.c @@ -50,8 +50,9 @@ Viking viking_fromVw(VikingVw vw) { } // Using the full using_cmap() macro to define [Viking -> int] hash map type: -using_cmap(vk, Viking, int, c_default_del, vikingvw_equals, vikingvw_hash, viking_del, - viking_fromVw, viking_toVw, VikingVw); +using_cmap(vk, Viking, int, c_default_del, c_default_clone, + vikingvw_equals, vikingvw_hash, + viking_del, viking_fromVw, viking_toVw, VikingVw); // cmap_vk uses vikingvw_hash() for hash value calculations, and vikingvw_equals() for equality test. // cmap_vk_del() will free all memory allocated for Viking keys and the hash table values. diff --git a/examples/complex.c b/examples/complex.c index 3dbf683d..6f665208 100644 --- a/examples/complex.c +++ b/examples/complex.c @@ -5,33 +5,33 @@ void check_del(float* v) {printf("destroy %g\n", *v);} -using_carray(f, float, check_del); // normally omit the last argument - float type need no destroy. -using_clist(y, carray2f, c_no_compare, carray2f_del); -using_cmap(g, int, clist_y, clist_y_del); -using_cmap_strkey(s, cmap_g, cmap_g_del); +using_carray(f, float, check_del, c_default_clone); // normally omit the last argument - float type need no destroy. +using_clist(a, carray2f, c_no_compare, carray2f_del); +using_cmap(l, int, clist_a, clist_a_del, clist_a_clone); +using_cmap_strkey(s, cmap_l, cmap_l_del, cmap_l_clone); int main() { int xdim = 4, ydim = 6; int x = 1, y = 5, tableKey = 42; const char* strKey = "first"; + cmap_l listMap = cmap_inits; + cmap_s myMap = cmap_inits; - { // Construct. - carray2f table = carray2f_init(ydim, xdim, 0.f); - printf("table: (%zu, %zu)\n", carray2_ydim(table), carray2_xdim(table)); - clist_y tableList = clist_inits; - // Put in some data. - cmap_g listMap = cmap_inits; - - *carray2f_at(&table, y, x) = 3.1415927f; // table[y][x] - clist_y_push_back(&tableList, table); - cmap_g_put(&listMap, tableKey, tableList); - cmap_s_put(&myMap, strKey, listMap); - } - { // Access the data entry - carray2f table = *clist_y_back(&cmap_g_find(&cmap_s_find(&myMap, strKey)->second, tableKey)->second); - printf("value (%d, %d) is: %f\n", y, x, *carray2f_at(&table, y, x)); - } + // Construct. + carray2f arr_a = carray2f_init(ydim, xdim, 0.f); + printf("arr_a: (%zu, %zu)\n", carray2f_ydim(arr_a), carray2f_xdim(arr_a)); + + clist_a tableList = clist_inits; + // Put in some data. + *carray2f_at(&arr_a, y, x) = 3.1415927f; // aa[y][x] + clist_a_push_back(&tableList, arr_a); + cmap_l_put(&listMap, tableKey, tableList); + cmap_s_put(&myMap, strKey, listMap); + + // Access the data entry + carray2f arr_b = *clist_a_back(&cmap_l_find(&cmap_s_find(&myMap, strKey)->second, tableKey)->second); + printf("value (%d, %d) is: %f\n", y, x, *carray2f_at(&arr_b, y, x)); cmap_s_del(&myMap); // free up everything! -} \ No newline at end of file +} diff --git a/examples/demos.c b/examples/demos.c index 5833bc5c..e460591b 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -185,8 +185,8 @@ void arraydemo1() carray2f a2 = carray3f_at1(&a3, 5); // sub-array reference: a2 = a3[5] carray1f a1 = carray3f_at2(&a3, 5, 4); // sub-array reference: a1 = a3[5][4] - printf("a3: %zu: (%zu, %zu, %zu) = %zu\n", sizeof(a3), carray3_xdim(a3), carray3_ydim(a3), carray3_zdim(a3), carray3_size(a3)); - printf("a2: %zu: (%zu, %zu) = %zu\n", sizeof(a2), carray2_xdim(a2), carray2_ydim(a2), carray2_size(a2)); + printf("a3: %zu: (%zu, %zu, %zu) = %zu\n", sizeof(a3), carray3f_xdim(a3), carray3f_ydim(a3), carray3f_zdim(a3), carray3f_size(a3)); + printf("a2: %zu: (%zu, %zu) = %zu\n", sizeof(a2), carray2f_xdim(a2), carray2f_ydim(a2), carray2f_size(a2)); printf("%f\n", a1.data[3]); // lookup a1[3] (=10.2f) printf("%f\n", *carray2f_at(&a2, 4, 3)); // lookup a2[4][3] (=10.2f) diff --git a/examples/inits.c b/examples/inits.c index 9138c5bb..59ed0ad2 100644 --- a/examples/inits.c +++ b/examples/inits.c @@ -5,7 +5,7 @@ #include #include -using_cmap(id, int, cstr_t, cstr_del); // Map of int -> cstr_t +using_cmap(id, int, cstr, cstr_del); // Map of int -> cstr using_cmap_strkey(cnt, int); typedef struct {int x, y;} ipair_t; diff --git a/examples/ptr.c b/examples/ptr.c index a9c4d258..37138952 100644 --- a/examples/ptr.c +++ b/examples/ptr.c @@ -8,23 +8,30 @@ Person* Person_make(Person* p, const char* name, const char* last) { p->name = cstr_from(name), p->last = cstr_from(last); return p; } +int Person_compare(const Person* p, const Person* q) { + int cmp = strcmp(p->name.str, q->name.str); + return cmp == 0 ? strcmp(p->last.str, q->last.str) : cmp; +} void Person_del(Person* p) { printf("del: %s\n", p->name.str); c_del(cstr, &p->name, &p->last); } -int Person_compare(const Person* p, const Person* q) { - int cmp = strcmp(p->name.str, q->name.str); - return cmp == 0 ? strcmp(p->last.str, q->last.str) : cmp; +Person Person_clone(Person p) { + p.name = cstr_clone(p.name); + p.last = cstr_clone(p.last); + return p; } +// 1. cvec of Person struct using_cvec(pe, Person, Person_compare, Person_del); -using_cptr(pu, Person, Person_compare, Person_del); -using_cvec(pu, Person*, cptr_pu_compare, cptr_pu_del); - -using_csptr(ps, Person, Person_compare, Person_del); -using_cvec(ps, csptr_ps, csptr_ps_compare, csptr_ps_del); +// 2. cvec of raw/owned pointers to Person +using_cptr(pe, Person, Person_compare, Person_del); +using_cvec(pp, Person*, cptr_pe_compare, cptr_pe_del, cptr_pe_clone); +// 3. cvec of shared-ptr to Person +using_csptr(pe, Person, Person_compare, Person_del); +using_cvec(ps, csptr_pe, csptr_pe_compare, csptr_pe_del); const char* names[] = { "Joe", "Jordan", @@ -33,36 +40,41 @@ const char* names[] = { }; int main() { - Person tmp; - cvec_pe vec = cvec_inits; - for (int i=0;i<6; i+=2) cvec_pe_push_back(&vec, *Person_make(&tmp, names[i], names[i+1])); - puts("cvec of Person:"); - cvec_pe_sort(&vec); - c_foreach (i, cvec_pe, vec) + cvec_pe vec1 = cvec_inits; + cvec_pp vec2 = cvec_inits; + cvec_ps vec3 = cvec_inits; + + for (int i = 0; i < 6; i += 2) { + Person tmp; + cvec_pe_push_back(&vec1, *Person_make(&tmp, names[i], names[i+1])); + cvec_pp_push_back(&vec2, Person_make(c_new(Person), names[i], names[i+1])); + cvec_ps_push_back(&vec3, csptr_pe_from(Person_make(c_new(Person), names[i], names[i+1]))); + } + puts("1. sorted cvec of Person :"); + cvec_pe_sort(&vec1); + c_foreach (i, cvec_pe, vec1) printf(" %s %s\n", i.ref->name.str, i.ref->last.str); - cvec_pu uvec = cvec_inits; - for (int i=0;i<6; i+=2) cvec_pu_push_back(&uvec, Person_make(c_new(Person), names[i], names[i+1])); - puts("cvec of cptr:"); - cvec_pu_sort(&uvec); - c_foreach (i, cvec_pu, uvec) + puts("\n2. sorted cvec of pointer to Person :"); + cvec_pp_sort(&vec2); + c_foreach (i, cvec_pp, vec2) printf(" %s %s\n", (*i.ref)->name.str, (*i.ref)->last.str); + + puts("\n3. sorted cvec of shared-pointer to Person :"); + cvec_ps_sort(&vec3); + c_foreach (i, cvec_ps, vec3) + printf(" %s %s\n", i.ref->get->name.str, i.ref->get->last.str); + + // share vec3[1] with elem variable. + csptr_pe elem = csptr_pe_clone(vec3.data[1]); - cvec_ps svec = cvec_inits; - for (int i=0;i<6; i+=2) cvec_ps_push_back(&svec, csptr_ps_from(Person_make(c_new(Person), names[i], names[i+1]))); - puts("cvec of csptr:"); - cvec_ps_sort(&svec); - c_foreach (i, cvec_ps, svec) - printf(" %s %s\n", (*i.ref).get->name.str, (*i.ref).get->last.str); - - csptr_ps x = csptr_ps_share(svec.data[1]); + puts("\nDestroy vec3:"); + cvec_ps_del(&vec3); // destroys all elements, but elem! + puts("\nDestroy vec2:"); + cvec_pp_del(&vec2); + puts("\nDestroy vec1:"); + cvec_pe_del(&vec1); - puts("\nDestroy svec:"); - cvec_ps_del(&svec); - puts("\nDestroy pvec:"); - cvec_pu_del(&uvec); - puts("\nDestroy vec:"); - cvec_pe_del(&vec); - puts("\nDestroy x:"); - csptr_ps_del(&x); + puts("\nDestroy elem:"); + csptr_pe_del(&elem); } \ No newline at end of file diff --git a/examples/share_ptr.c b/examples/share_ptr.c index 785333d0..18739d29 100644 --- a/examples/share_ptr.c +++ b/examples/share_ptr.c @@ -29,8 +29,8 @@ int main() { Person tmp = {cstr_from("Joe"), cstr_from("Jordan")}; csptr_pe joe = csptr_pe_make(tmp); - clist_pe_push_back(&queue, csptr_pe_share(joe)); - cvec_pe_push_back(&vec, csptr_pe_share(joe)); + clist_pe_push_back(&queue, csptr_pe_clone(joe)); + cvec_pe_push_back(&vec, csptr_pe_clone(joe)); puts("Push 10:"); c_forrange (i, 10) { @@ -38,7 +38,7 @@ int main() { p.get->name = cstr_from_fmt("Name %d", (i * 7) % 10); p.get->last = cstr_from_fmt("Last %d", (i * 7) % 10); clist_pe_push_back(&queue, p); - cvec_pe_push_back(&vec, csptr_pe_share(p)); // Don't forget to share! + cvec_pe_push_back(&vec, csptr_pe_clone(p)); // Don't forget to share! } c_foreach (i, clist_pe, queue) printf(" %s\n", i.ref->get->name.str); diff --git a/stc/carray.h b/stc/carray.h index 25c61ec7..12a97853 100644 --- a/stc/carray.h +++ b/stc/carray.h @@ -46,56 +46,14 @@ int main() } */ -#define carray1_xdim(a) ((a)._xdim & _carray_SUB) -#define carray1_size(a) carray1_xdim(a) - -#define carray2_xdim(a) carray1_xdim(a) -#define carray2_ydim(a) (a)._ydim -#define carray2_size(a) _carray2_size(&(a)._ydim) - -#define carray3_xdim(a) carray1_xdim(a) -#define carray3_ydim(a) carray2_ydim(a) -#define carray3_zdim(a) (a)._zdim -#define carray3_size(a) _carray3_size(&(a)._zdim) - -#define _carray_SUB (SIZE_MAX >> 1) -#define _carray_OWN (_carray_SUB + 1) - -STC_INLINE size_t -_carray2_size(const size_t* ydim) {return ydim[0] * ydim[-1];} -STC_INLINE size_t -_carray3_size(const size_t* zdim) {return zdim[0] * zdim[-1] * zdim[-2];} - - -#define using_carray_common(D, X, Value, valueDestroy) \ - typedef struct { Value *ref; } carray##D##X##_iter_t; \ -\ - STC_INLINE carray##D##X##_iter_t \ - carray##D##X##_begin(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(carray##D##X* a) { \ - carray##D##X##_iter_t it = {a->data + carray##D##_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) \ - valueDestroy(i.ref); \ - c_free(self->data); \ - } \ - } - #define using_carray(...) c_MACRO_OVERLOAD(using_carray, __VA_ARGS__) #define using_carray_2(X, Value) \ - using_carray_3(X, Value, c_default_del) - + using_carray_4(X, Value, c_default_del, c_default_clone) #define using_carray_3(X, Value, valueDestroy) \ + using_carray_4(X, Value, valueDestroy, Value##_clone) + +#define using_carray_4(X, Value, valueDestroy, valueClone) \ \ typedef Value carray1##X##_value_t; \ typedef carray1##X##_value_t carray2##X##_value_t, carray3##X##_value_t; \ @@ -115,9 +73,22 @@ _carray3_size(const size_t* zdim) {return zdim[0] * zdim[-1] * zdim[-2];} size_t _xdim, _ydim, _zdim; \ } carray3##X, carray3##X##_t; \ \ - using_carray_common(1, X, Value, valueDestroy) \ - using_carray_common(2, X, Value, valueDestroy) \ - using_carray_common(3, X, Value, valueDestroy) \ + 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 \ + carray3##X##_size(carray3##X a) {return _carray_xdim(a)*_carray_ydim(a)*_carray_zdim(a);} \ + STC_INLINE size_t \ + carray2##X##_ydim(carray2##X a) {return _carray_ydim(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(1, X, Value, valueDestroy, valueClone) \ + _using_carray_common(2, X, Value, valueDestroy, valueClone) \ + _using_carray_common(3, X, Value, valueDestroy, valueClone) \ \ STC_INLINE carray1##X \ carray1##X##_init(size_t xdim, Value val) { \ @@ -164,28 +135,68 @@ _carray3_size(const size_t* zdim) {return zdim[0] * zdim[-1] * zdim[-2];} \ STC_INLINE carray1##X \ carray2##X##_at1(carray2##X *a, size_t y) { \ - carray1##X sub = {a->data + y*carray2_xdim(*a), carray2_xdim(*a)}; \ + carray1##X sub = {a->data + y*_carray_xdim(*a), _carray_xdim(*a)}; \ return sub; \ } \ STC_INLINE Value* \ carray2##X##_at(carray2##X *a, size_t y, size_t x) { \ - return a->data + y*carray2_xdim(*a) + x; \ + return a->data + y*_carray_xdim(*a) + x; \ } \ \ STC_INLINE carray2##X \ carray3##X##_at1(carray3##X *a, size_t z) { \ - carray2##X sub = {a->data + z*a->_ydim*carray2_xdim(*a), carray3_xdim(*a), a->_ydim}; \ + carray2##X sub = {a->data + z*_carray_ydim(*a)*_carray_xdim(*a), _carray_xdim(*a), _carray_ydim(*a)}; \ return sub; \ } \ STC_INLINE carray1##X \ carray3##X##_at2(carray3##X *a, size_t z, size_t y) { \ - carray1##X sub = {a->data + (z*a->_ydim + y)*carray3_xdim(*a), carray3_xdim(*a)}; \ + carray1##X sub = {a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a), _carray_xdim(*a)}; \ return sub; \ } \ STC_INLINE Value* \ carray3##X##_at(carray3##X *a, size_t z, size_t y, size_t x) { \ - return a->data + (z*a->_ydim + y)*carray3_xdim(*a) + x; \ + return a->data + (z*_carray_ydim(*a) + y)*_carray_xdim(*a) + x; \ } \ typedef carray1##X carray1##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, valueDestroy, valueClone) \ + typedef struct { Value *ref; } carray##D##X##_iter_t; \ +\ + STC_INLINE carray##D##X##_iter_t \ + carray##D##X##_begin(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(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) \ + valueDestroy(i.ref); \ + c_free(self->data); \ + } \ + } \ + STC_INLINE carray##D##X \ + carray##D##X##_clone(carray##D##X arr) { \ + carray##D##X c = arr; size_t k = 0; \ + c.data = c_new_2(Value, carray##D##X##_size(arr)); \ + c_foreach_3 (i, carray##D##X, arr) \ + c.data[k++] = valueClone(*i.ref); \ + return c; \ + } \ + STC_INLINE size_t \ + carray##D##X##_xdim(carray##D##X a) {return _carray_xdim(a);} \ + #endif diff --git a/stc/cbitset.h b/stc/cbitset.h index 0005e693..2bb4cfec 100644 --- a/stc/cbitset.h +++ b/stc/cbitset.h @@ -49,7 +49,7 @@ int main() { #include #include "ccommon.h" -typedef struct cbitset { uint64_t* _arr; size_t size; } cbitset_t; +typedef struct cbitset { uint64_t* _arr; size_t size; } cbitset_t, cbitset; STC_API cbitset_t cbitset_with_size(size_t size, bool value); STC_API cbitset_t cbitset_from_str(const char* str); diff --git a/stc/ccommon.h b/stc/ccommon.h index 0df794df..a2d11729 100644 --- a/stc/ccommon.h +++ b/stc/ccommon.h @@ -82,6 +82,7 @@ #define c_less_compare(less, x, y) (less(y, x) - less(x, y)) #define c_default_compare(x, y) c_less_compare(c_default_less, x, y) #define c_default_from_raw(x) (x) +#define c_default_clone(x) (x) #define c_default_to_raw(ptr) (*(ptr)) #define c_default_del(ptr) ((void) (ptr)) diff --git a/stc/cdeq.h b/stc/cdeq.h index e543b37e..38445649 100644 --- a/stc/cdeq.h +++ b/stc/cdeq.h @@ -33,9 +33,9 @@ #define using_cdeq_2(X, Value) \ using_cdeq_3(X, Value, c_default_compare) #define using_cdeq_3(X, Value, valueCompare) \ - using_cdeq_4(X, Value, valueCompare, c_default_del) + using_cdeq_5(X, Value, valueCompare, c_default_del, c_default_clone) #define using_cdeq_4(X, Value, valueCompare, valueDestroy) \ - using_cdeq_5(X, Value, valueCompare, valueDestroy, c_default_from_raw) + using_cdeq_5(X, Value, valueCompare, valueDestroy, Value##_clone) #define using_cdeq_5(X, Value, valueCompare, valueDestroy, valueClone) \ using_cdeq_7(X, Value, valueCompare, valueDestroy, valueClone, c_default_to_raw, Value) #define using_cdeq_str() \ diff --git a/stc/clist.h b/stc/clist.h index e5171e1d..7c18b818 100644 --- a/stc/clist.h +++ b/stc/clist.h @@ -59,9 +59,9 @@ #define using_clist_2(X, Value) \ using_clist_3(X, Value, c_default_compare) #define using_clist_3(X, Value, valueCompare) \ - using_clist_4(X, Value, valueCompare, c_default_del) + using_clist_5(X, Value, valueCompare, c_default_del, c_default_clone) #define using_clist_4(X, Value, valueCompare, valueDestroy) \ - using_clist_5(X, Value, valueCompare, valueDestroy, c_default_from_raw) + using_clist_5(X, Value, valueCompare, valueDestroy, Value##_clone) #define using_clist_5(X, Value, valueCompare, valueDestroy, valueClone) \ using_clist_7(X, Value, valueCompare, valueDestroy, valueClone, c_default_to_raw, Value) #define using_clist_str() \ diff --git a/stc/cmap.h b/stc/cmap.h index aa4396f7..edeacfa9 100644 --- a/stc/cmap.h +++ b/stc/cmap.h @@ -73,24 +73,30 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; c_MACRO_OVERLOAD(using_cmap, __VA_ARGS__) #define using_cmap_3(X, Key, Mapped) \ - using_cmap_4(X, Key, Mapped, c_default_del) + using_cmap_5(X, Key, Mapped, c_default_del, c_default_clone) #define using_cmap_4(X, Key, Mapped, mappedDel) \ - using_cmap_6(X, Key, Mapped, mappedDel, c_default_equals, c_default_hash) + using_cmap_5(X, Key, Mapped, mappedDel, Mapped##_clone) -#define using_cmap_6(X, Key, Mapped, mappedDel, keyEquals, keyHash) \ - using_cmap_10(X, Key, Mapped, mappedDel, keyEquals, keyHash, c_default_del, \ - c_default_from_raw, c_default_to_raw, Key) +#define using_cmap_5(X, Key, Mapped, mappedDel, mappedClone) \ + using_cmap_7(X, Key, Mapped, mappedDel, mappedClone, c_default_equals, c_default_hash) -#define using_cmap_10(X, Key, Mapped, mappedDel, keyEqualsRaw, keyHashRaw, keyDel, \ +#define using_cmap_7(X, Key, Mapped, mappedDel, mappedClone, keyEquals, keyHash) \ + using_cmap_9(X, Key, Mapped, mappedDel, mappedClone, keyEquals, keyHash, c_default_del, c_default_clone) + +#define using_cmap_9(X, Key, Mapped, mappedDel, mappedClone, keyEquals, keyHash, keyDel, keyClone) \ + using_cmap_11(X, Key, Mapped, mappedDel, mappedClone, keyEquals, keyHash, keyDel, \ + keyClone, c_default_to_raw, Key) + +#define using_cmap_11(X, Key, Mapped, mappedDel, mappedClone, keyEqualsRaw, keyHashRaw, keyDel, \ keyFromRaw, keyToRaw, RawKey) \ _using_CHASH(X, cmap, Key, Mapped, mappedDel, keyEqualsRaw, keyHashRaw, keyDel, \ - keyFromRaw, keyToRaw, RawKey, c_default_from_raw, c_default_to_raw, Mapped) + keyFromRaw, keyToRaw, RawKey, mappedClone, c_default_to_raw, Mapped) -#define using_cmap_12(X, Key, Mapped, mappedDel, keyEqualsRaw, keyHashRaw, keyDel, \ - keyFromRaw, keyToRaw, RawKey, RawMapped, mappedFromRaw) \ +#define using_cmap_13(X, Key, Mapped, mappedDel, mappedFromRaw, mappedToRaw, RawMapped, \ + keyEqualsRaw, keyHashRaw, keyDel, keyFromRaw, keyToRaw, RawKey) \ _using_CHASH(X, cmap, Key, Mapped, mappedDel, keyEqualsRaw, keyHashRaw, keyDel, \ - keyFromRaw, keyToRaw, RawKey, mappedFromRaw, c_default_to_raw, RawMapped) + keyFromRaw, keyToRaw, RawKey, mappedFromRaw, mappedToRaw, RawMapped) /* cset: */ #define using_cset(...) \ @@ -100,7 +106,10 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; using_cset_4(X, Key, c_default_equals, c_default_hash) #define using_cset_4(X, Key, keyEquals, keyHash) \ - using_cset_6(X, Key, keyEquals, keyHash, c_default_del, c_default_from_raw) + using_cset_6(X, Key, keyEquals, keyHash, c_default_del, c_default_clone) + +#define using_cset_5(X, Key, keyEquals, keyHash, keyDel) \ + using_cset_6(X, Key, keyEquals, keyHash, keyDel, Key##_clone) #define using_cset_6(X, Key, keyEquals, keyHash, keyDel, keyClone) \ using_cset_8(X, Key, keyEquals, keyHash, keyDel, keyClone, c_default_to_raw, Key) @@ -111,20 +120,19 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; /* cset_str, cmap_str, cmap_strkey, cmap_strval: */ #define using_cset_str() \ - _using_CHASH_strkey(str, cset, cstr_t, _UNUSED_) - + _using_CHASH_strkey(str, cset, cstr_t, _UNUSED_, _UNUSED_) #define using_cmap_str() \ _using_CHASH(str, cmap, cstr_t, cstr_t, cstr_del, cstr_equals_raw, cstr_hash_raw, cstr_del, \ cstr_from, cstr_to_raw, const char*, cstr_from, cstr_to_raw, const char*) #define using_cmap_strkey(...) \ c_MACRO_OVERLOAD(using_cmap_strkey, __VA_ARGS__) - #define using_cmap_strkey_2(X, Mapped) \ - _using_CHASH_strkey(X, cmap, Mapped, c_default_del) - + _using_CHASH_strkey(X, cmap, Mapped, c_default_del, c_default_clone) #define using_cmap_strkey_3(X, Mapped, mappedDel) \ - _using_CHASH_strkey(X, cmap, Mapped, mappedDel) + _using_CHASH_strkey(X, cmap, Mapped, mappedDel, Mapped##_clone) +#define using_cmap_strkey_4(X, Mapped, mappedDel, mappedClone) \ + _using_CHASH_strkey(X, cmap, Mapped, mappedDel, mappedClone) #define using_cmap_strval(...) \ c_MACRO_OVERLOAD(using_cmap_strval, __VA_ARGS__) @@ -133,7 +141,10 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; using_cmap_strval_4(X, Key, c_default_equals, c_default_hash) #define using_cmap_strval_4(X, Key, keyEquals, keyHash) \ - using_cmap_strval_6(X, Key, keyEquals, keyHash, c_default_del, c_default_from_raw) + using_cmap_strval_6(X, Key, keyEquals, keyHash, c_default_del, c_default_clone) + +#define using_cmap_strval_5(X, Key, keyEquals, keyHash, keyDel) \ + using_cmap_strval_6(X, Key, keyEquals, keyHash, keyDel, Key##_clone) #define using_cmap_strval_6(X, Key, keyEquals, keyHash, keyDel, keyClone) \ using_cmap_strval_8(X, Key, keyEquals, keyHash, keyDel, keyClone, c_default_to_raw, Key) @@ -142,9 +153,9 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; _using_CHASH(X, cmap, Key, cstr_t, cstr_del, keyEquals, keyHash, keyDel, \ keyFromRaw, keyToRaw, RawKey, cstr_from, cstr_to_raw, const char*) -#define _using_CHASH_strkey(X, ctype, Mapped, mappedDel) \ +#define _using_CHASH_strkey(X, ctype, Mapped, mappedDel, mappedClone) \ _using_CHASH(X, ctype, cstr_t, Mapped, mappedDel, cstr_equals_raw, cstr_hash_raw, cstr_del, \ - cstr_from, cstr_to_raw, const char*, c_default_from_raw, c_default_to_raw, Mapped) + cstr_from, cstr_to_raw, const char*, mappedClone, c_default_to_raw, Mapped) #define CSET_ONLY_cset(...) __VA_ARGS__ #define CSET_ONLY_cmap(...) @@ -211,6 +222,8 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; } \ STC_API ctype##_##X \ ctype##_##X##_with_capacity(size_t cap); \ + STC_API ctype##_##X \ + ctype##_##X##_clone(ctype##_##X m); \ STC_API void \ ctype##_##X##_reserve(ctype##_##X* self, size_t size); \ STC_API void \ @@ -303,14 +316,14 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; STC_API uint32_t c_default_hash32(const void* data, size_t len); \ \ _c_implement_CHASH(X, ctype, Key, Mapped, mappedDel, keyEqualsRaw, keyHashRaw, keyDel, \ - keyFromRaw, keyToRaw, RawKey, RawMapped, mappedFromRaw) \ + keyFromRaw, keyToRaw, RawKey, mappedFromRaw, mappedToRaw, RawMapped) \ typedef ctype##_##X ctype##_##X##_t /* -------------------------- IMPLEMENTATION ------------------------- */ #if !defined(STC_HEADER) || defined(STC_IMPLEMENTATION) #define _c_implement_CHASH(X, ctype, Key, Mapped, mappedDel, keyEqualsRaw, keyHashRaw, keyDel, \ - keyFromRaw, keyToRaw, RawKey, RawMapped, mappedFromRaw) \ + keyFromRaw, keyToRaw, RawKey, mappedFromRaw, mappedToRaw, RawMapped) \ STC_DEF ctype##_##X \ ctype##_##X##_with_capacity(size_t cap) { \ ctype##_##X h = ctype##_inits; \ @@ -386,6 +399,21 @@ typedef struct {size_t idx; uint32_t hx;} cmap_bucket_t, cset_bucket_t; } \ return res; \ } \ +\ + STC_DEF ctype##_##X \ + ctype##_##X##_clone(ctype##_##X m) { \ + ctype##_##X clone = { \ + c_new_2(ctype##_##X##_value_t, m.bucket_count), \ + (uint8_t *) memcpy(c_malloc(m.bucket_count + 1), m._hashx, m.bucket_count + 1), \ + m.size, m.bucket_count, m.max_load_factor, m.shrink_limit_factor \ + }; \ + ctype##_##X##_value_t *e = m.table, *end = e + m.bucket_count, *dst = clone.table; \ + for (uint8_t *hx = m._hashx; e != end; ++hx, ++e, ++dst) if (*hx) { \ + KEY_REF_##ctype(dst) = keyFromRaw(keyToRaw(&KEY_REF_##ctype(e))); \ + CMAP_ONLY_##ctype( dst->second = mappedFromRaw(mappedToRaw(&e->second)); ) \ + } \ + return clone; \ + } \ \ STC_DEF void \ ctype##_##X##_reserve(ctype##_##X* self, size_t newcap) { \ @@ -449,7 +477,7 @@ STC_DEF uint32_t c_default_hash32(const void* data, size_t len) { #else #define _c_implement_CHASH(X, ctype, Key, Mapped, mappedDel, keyEqualsRaw, keyHashRaw, keyDel, \ - keyFromRaw, keyToRaw, RawKey, RawMapped, mappedFromRaw) + keyFromRaw, keyToRaw, RawKey, mappedFromRaw, mappedToRaw, RawMapped) #endif #endif diff --git a/stc/cptr.h b/stc/cptr.h index 23e1f09f..d028977c 100644 --- a/stc/cptr.h +++ b/stc/cptr.h @@ -65,9 +65,12 @@ int main() { using_cptr_3(X, Value, c_default_compare) #define using_cptr_3(X, Value, valueCompare) \ - using_cptr_4(X, Value, valueCompare, c_default_del) + using_cptr_5(X, Value, valueCompare, c_default_del, c_default_clone) #define using_cptr_4(X, Value, valueCompare, valueDestroy) \ + using_cptr_5(X, Value, valueCompare, valueDestroy, Value##_clone) + +#define using_cptr_5(X, Value, valueCompare, valueDestroy, valueClone) \ typedef Value cptr_##X##_value_t; \ typedef cptr_##X##_value_t *cptr_##X; \ \ @@ -76,6 +79,12 @@ int main() { valueDestroy(*self); \ c_free(*self); \ } \ + STC_INLINE cptr_##X \ + cptr_##X##_clone(cptr_##X ptr) { \ + cptr_##X clone = c_new_1(Value); \ + *clone = valueClone(*ptr); \ + return clone; \ + } \ \ STC_INLINE void \ cptr_##X##_reset(cptr_##X* self, cptr_##X##_value_t* p) { \ @@ -111,7 +120,7 @@ using_csptr(pe, Person, Person_del); int main() { csptr_pe p = csptr_pe_make(Person_make(c_new(Person), "Joe", "Jordan")); - csptr_pe q = csptr_pe_share(p); // share the pointer + csptr_pe q = csptr_pe_clone(p); // share the pointer printf("%s %s: %d\n", q.get->name.str, q.get->last.str, *q.use_count); c_del(csptr_pe, &p, &q); @@ -174,7 +183,7 @@ typedef long atomic_count_t; *ptr.get = val, *ptr.use_count = 1; return ptr; \ } \ STC_INLINE csptr_##X \ - csptr_##X##_share(csptr_##X ptr) { \ + csptr_##X##_clone(csptr_##X ptr) { \ if (ptr.use_count) atomic_increment(ptr.use_count); \ return ptr; \ } \ diff --git a/stc/cstr.h b/stc/cstr.h index aad1d7fc..32b2eb52 100644 --- a/stc/cstr.h +++ b/stc/cstr.h @@ -30,7 +30,7 @@ #include /* vsnprintf */ #include -typedef struct cstr { char* str; } cstr_t; +typedef struct cstr { char* str; } cstr_t, cstr; typedef struct { char *ref; } cstr_iter_t; typedef char cstr_value_t; diff --git a/stc/cvec.h b/stc/cvec.h index 1fd6add5..62fc9ea3 100644 --- a/stc/cvec.h +++ b/stc/cvec.h @@ -33,9 +33,9 @@ #define using_cvec_2(X, Value) \ using_cvec_3(X, Value, c_default_compare) #define using_cvec_3(X, Value, valueCompare) \ - using_cvec_4(X, Value, valueCompare, c_default_del) + using_cvec_5(X, Value, valueCompare, c_default_del, c_default_clone) #define using_cvec_4(X, Value, valueCompare, valueDestroy) \ - using_cvec_5(X, Value, valueCompare, valueDestroy, c_default_from_raw) + using_cvec_5(X, Value, valueCompare, valueDestroy, Value##_clone) #define using_cvec_5(X, Value, valueCompare, valueDestroy, valueClone) \ using_cvec_7(X, Value, valueCompare, valueDestroy, valueClone, c_default_to_raw, Value) #define using_cvec_str() \ -- cgit v1.2.3