summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/cdeq_api.md2
-rw-r--r--docs/clist_api.md2
-rw-r--r--docs/cmap_api.md18
-rw-r--r--docs/cptr_api.md14
-rw-r--r--docs/cset_api.md6
-rw-r--r--docs/cvec_api.md2
-rw-r--r--examples/advanced.c5
-rw-r--r--examples/complex.c42
-rw-r--r--examples/demos.c4
-rw-r--r--examples/inits.c2
-rw-r--r--examples/ptr.c82
-rw-r--r--examples/share_ptr.c6
-rw-r--r--stc/carray.h119
-rw-r--r--stc/cbitset.h2
-rw-r--r--stc/ccommon.h1
-rw-r--r--stc/cdeq.h4
-rw-r--r--stc/clist.h4
-rw-r--r--stc/cmap.h74
-rw-r--r--stc/cptr.h15
-rw-r--r--stc/cstr.h2
-rw-r--r--stc/cvec.h4
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 <stc/cpque.h>
#include <stc/clist.h>
-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<Person>:");
- 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<Person>:");
- 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 <string.h>
#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; \
@@ -387,6 +400,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) { \
size_t oldcap = self->bucket_count; \
@@ -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 <stdio.h> /* vsnprintf */
#include <ctype.h>
-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() \