diff options
| author | Tylo <[email protected]> | 2020-06-22 15:00:44 +0200 |
|---|---|---|
| committer | Tylo <[email protected]> | 2020-06-22 15:00:44 +0200 |
| commit | 6b060a2393cc3a20f19e0e482e335c959dd845bb (patch) | |
| tree | c98d864b6df792d865d717e5cad1033b85bb93d3 | |
| parent | 389b09b637a00678f01affbea7491ce9dfdefd0d (diff) | |
| download | STC-modified-6b060a2393cc3a20f19e0e482e335c959dd845bb.tar.gz STC-modified-6b060a2393cc3a20f19e0e482e335c959dd845bb.zip | |
Updated CArray to support destructors, and added underscore before used defined tag - for consistency with the other containers.
Changed map/set type-tag for CHash to upper case MAP/SET. Makes it clearer it is a tag and not a type or variable.
Added complex example to README.md demonstrating capability of nested containers, using custom destructors.
| -rw-r--r-- | README.md | 69 | ||||
| -rw-r--r-- | examples/advanced.c | 2 | ||||
| -rw-r--r-- | examples/benchmark.c | 2 | ||||
| -rw-r--r-- | examples/demos.c | 33 | ||||
| -rw-r--r-- | stc/carray.h | 147 | ||||
| -rw-r--r-- | stc/chash.h | 8 |
6 files changed, 170 insertions, 91 deletions
@@ -100,18 +100,39 @@ Demos The first example demonstrates an advanced complex type that shows some of the capability of the library. Look at the simpler to understand this better. This create one element into a large data structure (using C++ template syntax for describing the type):
**CHash_map**< *CString*, *CHash_map*< *int*, *CList*< *CArray2*< *float* > > > >
```
-#include "<stc/cstring.h>
-#include "<stc/chash.h>
-#include "<stc/clist.h>
-#include "<stc/carray.h>
+#include "stc/cstring.h"
+#include "stc/chash.h"
+#include "stc/clist.h"
+#include "stc/carray.h"
-declare_CArray2(f, float);
-declare_CList(a2, CArray2_f, carray_f_destroy);
-declare_CHash(m2, map, CList_a2, clist_a2_destroy);
-declare_CHash(m, map, CHash_m2, chash_m2_destroy);
+void check_destroy(float* v) {printf("destroy %g\n", *v);}
+
+declare_CArray(f, float, check_destroy);
+declare_CList(t2, CArray2_f, carray2_f_destroy, c_noCompare);
+declare_CHash(lm, MAP, int, CList_t2, clist_t2_destroy);
+declare_CHash_string(m, MAP, CHash_lm, chash_lm_destroy);
int main() {
-
+ int dim1 = 4, dim2 = 6;
+ CHash_m theMap = chash_init;
+ {
+ // Construct.
+ CArray2_f table = carray2_f_make(dim1, dim2, 0.f);
+ CList_t2 tableList = clist_init;
+ CHash_lm listMap = chash_init;
+
+ // Put in some data.
+ carray2_f_data(table, 2)[5] = 3.1415927; // table[2][5]
+ clist_t2_pushBack(&tableList, table);
+ chash_lm_put(&listMap, 42, tableList);
+ chash_m_put(&theMap, "First", listMap);
+ }
+
+ // Access the data entry
+ CArray2_f tab = clist_back(chash_lm_get(&chash_m_get(&theMap, "First")->value, 42)->value);
+ printf("value is: %f\n", carray2_f_value(tab, 3, 5));
+
+ chash_m_destroy(&theMap); // destroy the whole shebang!
}
```
**CString**
@@ -179,7 +200,7 @@ int main() { **CHash map** of *int -> int*
```
#include <stc/chash.h>
-declare_CHash(ii, map, int, int);
+declare_CHash(ii, MAP, int, int);
int main() {
CHash_ii nums = chash_init;
@@ -194,7 +215,7 @@ int main() { ```
#include <stc/cstring.h>
#include <stc/chash.h>
-declare_CHash_string(s, set); // Shorthand macro for the general declare_CHash expansion.
+declare_CHash_string(s, SET); // Shorthand macro for the general declare_CHash expansion.
// CString keys are managed internally, although CHash is ignorant of CString.
int main() {
@@ -213,7 +234,7 @@ int main() { ```
#include <stc/cstring.h>
#include <stc/chash.h>
-declare_CHash_string(ss, map, CString, cstring_destroy);
+declare_CHash_string(ss, MAP, CString, cstring_destroy);
int main() {
CHash_ss table = chash_init;
@@ -249,26 +270,26 @@ int main() { clist_i_destroy(&list);
}
```
-**CArray**
+**CArray**. Heap allocated 1D, 2D and 3D array in one memory block, with sub-arrays.
```
#include <stc/carray.h>
declare_CArray(f, float);
int main()
{
- CArray3f a3 = carray3f_make(30, 20, 10);
- carray3f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
- CArray2f a2 = carray3f_at(a3, 5); // sub-array reference (no data copy).
+ CArray3_f a3 = carray3f_make(30, 20, 10, 0.f);
+ carray3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
+ CArray2_f a2 = carray3_f_at(a3, 5); // sub-array reference (no data copy).
- printf("%f\n", carray2f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
- printf("%f\n", carray2f_data(a2, 4)[3]); // same, but this is writable.
- printf("%f\n", carray2f_at(a2, 4).data[3]); // same, via sub-array access.
+ printf("%f\n", carray2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
+ printf("%f\n", carray2_f_data(a2, 4)[3]); // same, but this is writable.
+ printf("%f\n", carray2_f_at(a2, 4).data[3]); // same, via sub-array access.
- printf("%f\n", carray3f_value(a3, 5, 4, 3)); // same data location, via a3 array.
- printf("%f\n", carray3f_data(a3, 5, 4)[3]);
- printf("%f\n", carray3f_at2(a3, 5, 4).data[3]);
+ printf("%f\n", carray3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
+ printf("%f\n", carray3_f_data(a3, 5, 4)[3]);
+ printf("%f\n", carray3_f_at2(a3, 5, 4).data[3]);
- carray_destroy(a2); // does nothing, since it is a sub-array.
- carray_destroy(a3); // also invalidates a2.
+ carray_f_destroy(&a2); // does nothing, since it is a sub-array.
+ carray_f_destroy(&a3); // also invalidates a2.
}
```
diff --git a/examples/advanced.c b/examples/advanced.c index 092e3f01..37b67531 100644 --- a/examples/advanced.c +++ b/examples/advanced.c @@ -64,7 +64,7 @@ size_t personview_hash(const struct PersonView* pv, size_t ignore) { /*``` With this in place, we can declare the map Person -> int: ```*/ -declare_CHash(ex, map, struct Person, int, c_emptyDestroy, personview_hash, personview_compare, +declare_CHash(ex, MAP, struct Person, int, c_emptyDestroy, personview_hash, personview_compare, struct PersonView, person_destroy, person_getView, person_fromView); /*``` Note we use struct PersonView to put keys in the map, but keys are stored as struct Person with proper dynamically allocated CStrings to store name and surname. diff --git a/examples/benchmark.c b/examples/benchmark.c index 4d7a2fd1..dd070ff4 100644 --- a/examples/benchmark.c +++ b/examples/benchmark.c @@ -19,7 +19,7 @@ static inline uint32_t fibonacci_hash(const void* data, size_t len) { const uint64_t key = *(const uint64_t *) data;
return (uint32_t) (key * 11400714819323198485llu);
}
-declare_CHash(ii, map, int64_t, int64_t, c_emptyDestroy, fibonacci_hash); // c_lowbias32Hash);
+declare_CHash(ii, MAP, int64_t, int64_t, c_emptyDestroy, fibonacci_hash); // c_lowbias32Hash);
KHASH_MAP_INIT_INT64(ii, uint64_t)
diff --git a/examples/demos.c b/examples/demos.c index b2fa32ec..e05fa269 100644 --- a/examples/demos.c +++ b/examples/demos.c @@ -1,5 +1,6 @@ #include "../stc/cvector.h" #include "../stc/clist.h" +#include "../stc/carray.h" #include "../stc/chash.h" #include "../stc/cstring.h" @@ -98,7 +99,7 @@ void listdemo1() clist_ix_destroy(&nums); } -declare_CHash(i, set, int); +declare_CHash(i, SET, int); void setdemo1() { @@ -113,7 +114,7 @@ void setdemo1() } -declare_CHash(ii, map, int, int); +declare_CHash(ii, MAP, int, int); void mapdemo1() { @@ -127,7 +128,7 @@ void mapdemo1() } -declare_CHash_string(si, map, int); // Shorthand macro for the general declare_CHash expansion. +declare_CHash_string(si, MAP, int); // Shorthand macro for the general declare_CHash expansion. void mapdemo2() { @@ -149,7 +150,7 @@ void mapdemo2() } -declare_CHash_string(ss, map, CString, cstring_destroy); +declare_CHash_string(ss, MAP, CString, cstring_destroy); void mapdemo3() { @@ -169,6 +170,29 @@ void mapdemo3() +declare_CArray(f, float); + +int arraydemo1() +{ + printf("\nARRAYDEMO1\n"); + CArray3_f a3 = carray3_f_make(30, 20, 10, 0.f); + carray3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3] + CArray2_f a2 = carray3_f_at(a3, 5); // sub-array reference (no data copy). + + printf("%f\n", carray2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f) + printf("%f\n", carray2_f_data(a2, 4)[3]); // same, but this is writable. + printf("%f\n", carray2_f_at(a2, 4).data[3]); // same, via sub-array access. + + printf("%f\n", carray3_f_value(a3, 5, 4, 3)); // same data location, via a3 array. + printf("%f\n", carray3_f_data(a3, 5, 4)[3]); + printf("%f\n", carray3_f_at2(a3, 5, 4).data[3]); + + carray2_f_destroy(&a2); // does nothing, since it is a sub-array. + carray3_f_destroy(&a3); // also invalidates a2. +} + + + int main() { stringdemo1(); @@ -179,4 +203,5 @@ int main() mapdemo1(); mapdemo2(); mapdemo3(); + arraydemo1(); } diff --git a/stc/carray.h b/stc/carray.h index 502a0038..b85170b4 100644 --- a/stc/carray.h +++ b/stc/carray.h @@ -32,20 +32,20 @@ declare_CArray(f, float); int main()
{
- CArray3f a3 = carray3f_make(30, 20, 10);
- carray3f_data(a3, 5, 4)[3] = 10.2f;
- CArray2f a2 = carray3f_at(a3, 5);
+ CArray3_f a3 = carray3f_make(30, 20, 10, 0.f);
+ carray3_f_data(a3, 5, 4)[3] = 10.2f; // a3[5][4][3]
+ CArray2_f a2 = carray3_f_at(a3, 5); // sub-array reference (no data copy).
- printf("%f\n", carray2f_value(a2, 4, 3));
- printf("%f\n", carray2f_data(a2, 4)[3]);
- printf("%f\n", carray2f_at(a2, 4).data[3]);
+ printf("%f\n", carray2_f_value(a2, 4, 3)); // readonly lookup a2[4][3] (=10.2f)
+ printf("%f\n", carray2_f_data(a2, 4)[3]); // same, but this is writable.
+ printf("%f\n", carray2_f_at(a2, 4).data[3]); // same, via sub-array access.
- printf("%f\n", carray3f_value(a3, 5, 4, 3));
- printf("%f\n", carray3f_data(a3, 5, 4)[3]);
- printf("%f\n", carray3f_at2(a3, 5, 4).data[3]);
+ printf("%f\n", carray3_f_value(a3, 5, 4, 3)); // same data location, via a3 array.
+ printf("%f\n", carray3_f_data(a3, 5, 4)[3]);
+ printf("%f\n", carray3_f_at2(a3, 5, 4).data[3]);
- carray_destroy(a3);
- carray_destroy(a2); // not needed, but no harm.
+ carray_f_destroy(&a2); // does nothing, since it is a sub-array.
+ carray_f_destroy(&a3); // also invalidates a2.
}
*/
@@ -55,67 +55,100 @@ int main() #define carray1_size(a) ((a).xdim)
#define carray2_size(a) ((a)._yxdim)
#define carray3_size(a) ((a)._zdim * (a)._yxdim)
-#define carray_destroy(a) free((a)._array)
-#define declare_CArray(tag, T) \
- c_struct (CArray1##tag) { \
- T *data, *_array; \
- uint32_t xdim; \
- }; \
- c_struct (CArray2##tag) { \
- T *data, *_array; \
- uint32_t xdim, _yxdim; \
- }; \
- c_struct (CArray3##tag) { \
- T *data, *_array; \
- uint32_t xdim, _yxdim, _zdim; \
- }; \
+#define declare_CArray(...) c_MACRO_OVERLOAD(declare_CArray, __VA_ARGS__)
+
+#define declare_CArray_2(tag, Value) \
+ declare_CArray_3(tag, Value, c_emptyDestroy)
+
+
+#define declare_CArray_3(tag, Value, valueDestroy) \
+ typedef struct { \
+ Value *data; uint32_t owned, xdim; \
+ } CArray1_##tag; \
+ \
+ typedef struct { \
+ Value *data; uint32_t owned, xdim; \
+ size_t _yxdim; \
+ } CArray2_##tag; \
+ \
+ typedef struct { \
+ Value *data; uint32_t owned, xdim; \
+ size_t _yxdim; uint32_t _zdim; \
+ } CArray3_##tag; \
\
- static inline CArray1##tag \
- carray1##tag##_make(size_t xdim) { \
- T* m = c_new_2(T, xdim); \
- return (CArray1##tag) {m, m, xdim}; \
+ static inline void \
+ carray1_##tag##_destroy(CArray1_##tag* self) { \
+ const size_t n = carray1_size(*self); Value* a = self->data; \
+ if (self->owned) {for (size_t i=0; i<n; ++i) valueDestroy(&a[i]); free(a);} \
} \
- static inline CArray2##tag \
- carray2##tag##_make(size_t ydim, size_t xdim) { \
- T* m = c_new_2(T, ydim*xdim); \
- return (CArray2##tag) {m, m, xdim, ydim*xdim}; \
+ static inline void \
+ carray2_##tag##_destroy(CArray2_##tag* self) { \
+ const size_t n = carray2_size(*self); Value* a = self->data; \
+ if (self->owned) {for (size_t i=0; i<n; ++i) valueDestroy(&a[i]); free(a);} \
} \
- static inline CArray3##tag \
- carray3##tag##_make(size_t zdim, size_t ydim, size_t xdim) { \
- T* m = c_new_2(T, zdim*ydim*xdim); \
- return (CArray3##tag) {m, m, xdim, ydim*xdim, zdim}; \
+ static inline void \
+ carray3_##tag##_destroy(CArray3_##tag* self) { \
+ const size_t n = carray3_size(*self); Value* a = self->data; \
+ if (self->owned) {for (size_t i=0; i<n; ++i) valueDestroy(&a[i]); free(a);} \
} \
\
- static inline CArray1##tag \
- carray2##tag##_at(CArray2##tag a, size_t y) { \
- return (CArray1##tag) {a.data + y*a.xdim, NULL, a.xdim}; \
+ static inline CArray1_##tag \
+ carray1_##tag##_make(size_t xdim, Value val) { \
+ Value* m = c_new_2(Value, xdim); \
+ for (size_t i=0; i<xdim; ++i) m[i] = val; \
+ CArray1_##tag a = {m, true, xdim}; \
+ return a; \
} \
- static inline T* \
- carray2##tag##_data(CArray2##tag a, size_t y) { \
+ static inline CArray2_##tag \
+ carray2_##tag##_make(size_t ydim, size_t xdim, Value val) { \
+ size_t n = ydim * xdim; \
+ Value* m = c_new_2(Value, n); \
+ for (size_t i=0; i<n; ++i) m[i] = val; \
+ CArray2_##tag a = {m, true, xdim, ydim * xdim}; \
+ return a; \
+ } \
+ static inline CArray3_##tag \
+ carray3_##tag##_make(size_t zdim, size_t ydim, size_t xdim, Value val) { \
+ size_t n = zdim * ydim * xdim; \
+ Value* m = c_new_2(Value, n); \
+ for (size_t i=0; i<n; ++i) m[i] = val; \
+ CArray3_##tag a = {m, true, xdim, ydim * xdim, zdim}; \
+ return a; \
+ } \
+ \
+ static inline CArray1_##tag \
+ carray2_##tag##_at(CArray2_##tag a, size_t y) { \
+ CArray1_##tag sub = {a.data + y*a.xdim, false, a.xdim}; \
+ return sub; \
+ } \
+ static inline Value* \
+ carray2_##tag##_data(CArray2_##tag a, size_t y) { \
return a.data + y*a.xdim; \
} \
- static inline T \
- carray2##tag##_value(CArray2##tag a, size_t y, size_t x) { \
+ static inline Value \
+ carray2_##tag##_value(CArray2_##tag a, size_t y, size_t x) { \
return a.data[ y*a.xdim + x ]; \
} \
\
- static inline CArray2##tag \
- carray3##tag##_at(CArray3##tag a, size_t z) { \
- return (CArray2##tag) {a.data + z*a._yxdim, NULL, a.xdim, a._yxdim}; \
+ static inline CArray2_##tag \
+ carray3_##tag##_at(CArray3_##tag a, size_t z) { \
+ CArray2_##tag sub = {a.data + z*a._yxdim, false, a.xdim, a._yxdim}; \
+ return sub; \
} \
- static inline CArray1##tag \
- carray3##tag##_at2(CArray3##tag a, size_t z, size_t y) { \
- return (CArray1##tag) {a.data + z*a._yxdim + y*a.xdim, NULL, a.xdim}; \
+ static inline CArray1_##tag \
+ carray3_##tag##_at2(CArray3_##tag a, size_t z, size_t y) { \
+ CArray1_##tag sub = {a.data + z*a._yxdim + y*a.xdim, false, a.xdim}; \
+ return sub; \
} \
- static inline T* \
- carray3##tag##_data(CArray3##tag a, size_t z, size_t y) { \
+ static inline Value* \
+ carray3_##tag##_data(CArray3_##tag a, size_t z, size_t y) { \
return a.data + z*a._yxdim + y*a.xdim; \
} \
- static inline T \
- carray3##tag##_value(CArray3##tag a, size_t z, size_t y, size_t x) { \
+ static inline Value \
+ carray3_##tag##_value(CArray3_##tag a, size_t z, size_t y, size_t x) { \
return a.data[ z*a._yxdim + y*a.xdim + x ]; \
} \
- typedef T carray_##tag##_t
-
-#endif
\ No newline at end of file + typedef Value CArrayValue_##tag
+
+#endif
diff --git a/stc/chash.h b/stc/chash.h index a53f7d75..33f3e02c 100644 --- a/stc/chash.h +++ b/stc/chash.h @@ -95,10 +95,10 @@ enum {chash_HASH = 0x7f, chash_USED = 0x80}; declare_CHash_11(tag, type, CString, Value, valueDestroy, cstring_hashRaw, cstring_equalsRaw, \
const char*, cstring_destroy, cstring_getRaw, cstring_make)
-#define _chash1_set(x)
-#define _chash2_set(x, y) x
-#define _chash1_map(x) x
-#define _chash2_map(x, y) x, y
+#define _chash1_SET(x)
+#define _chash2_SET(x, y) x
+#define _chash1_MAP(x) x
+#define _chash2_MAP(x, y) x, y
/* CHash full: */
#define declare_CHash_11(tag, type, Key, Value, valueDestroy, keyHashRaw, keyEqualsRaw, \
|
