From 41c8dfe25d9ef785c3b8a9f00f042a61669af7e6 Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 4 Jan 2023 16:33:52 +0100 Subject: Improved a few examples. --- docs/cmap_api.md | 4 +-- docs/cpque_api.md | 2 +- docs/cset_api.md | 4 +-- docs/csmap_api.md | 2 +- docs/csset_api.md | 2 +- include/stc/ccommon.h | 18 ++++++------ misc/examples/cpque.c | 72 ----------------------------------------------- misc/examples/functor.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ misc/examples/intrusive.c | 61 ++++++++++++++++++++------------------- 9 files changed, 116 insertions(+), 117 deletions(-) delete mode 100644 misc/examples/cpque.c create mode 100644 misc/examples/functor.c diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 3946196b..10bfb040 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -37,8 +37,8 @@ See the c++ class [std::unordered_map](https://en.cppreference.com/w/cpp/contain #define i_valto // convertion func i_val* => i_valraw #define i_size // default: uint32_t. If defined, table expand 2x (else 1.5x) -#define i_hash_functor // advanced, see examples/cpque.c for similar usage. -#define i_eq_functor // advanced, see examples/cpque.c for similar usage. +#define i_hash_functor // advanced, see examples/functor.c for similar usage. +#define i_eq_functor // advanced, see examples/functor.c for similar usage. #define i_tag // alternative typename: cmap_{i_tag}. i_tag defaults to i_val #include ``` diff --git a/docs/cpque_api.md b/docs/cpque_api.md index 790b902c..392d3149 100644 --- a/docs/cpque_api.md +++ b/docs/cpque_api.md @@ -18,7 +18,7 @@ See the c++ class [std::priority_queue](https://en.cppreference.com/w/cpp/contai #define i_valfrom // convertion func i_valraw => i_val #define i_valto // convertion func i_val* => i_valraw. -#define i_less_functor // takes self as first argument. See examples/cpque.c for usage. +#define i_less_functor // takes self as first argument. See examples/functor.c for usage. #define i_tag // alternative typename: cpque_{i_tag}. i_tag defaults to i_val #include ``` diff --git a/docs/cset_api.md b/docs/cset_api.md index 43cbdead..aff8506a 100644 --- a/docs/cset_api.md +++ b/docs/cset_api.md @@ -19,8 +19,8 @@ A **cset** is an associative container that contains a set of unique objects of #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy #define i_size // default: uint32_t. If defined, table expand 2x (else 1.5x) -#define i_hash_functor // advanced, see examples/cpque.c for similar usage. -#define i_eq_functor // advanced, see examples/cpque.c for similar usage. +#define i_hash_functor // advanced, see examples/functor.c for similar usage. +#define i_eq_functor // advanced, see examples/functor.c for similar usage. #define i_tag // alternative typename: cmap_{i_tag}. i_tag defaults to i_val #include ``` diff --git a/docs/csmap_api.md b/docs/csmap_api.md index 394d3451..20346735 100644 --- a/docs/csmap_api.md +++ b/docs/csmap_api.md @@ -32,7 +32,7 @@ See the c++ class [std::map](https://en.cppreference.com/w/cpp/container/map) fo #define i_valfrom // convertion func i_valraw => i_val #define i_valto // convertion func i_val* => i_valraw -#define i_cmp_functor // advanced, see examples/cpque.c for similar usage. +#define i_cmp_functor // advanced, see examples/functor.c for similar usage. #define i_tag // alternative typename: csmap_{i_tag}. i_tag defaults to i_val #include ``` diff --git a/docs/csset_api.md b/docs/csset_api.md index 5b833af5..e242b8e4 100644 --- a/docs/csset_api.md +++ b/docs/csset_api.md @@ -18,7 +18,7 @@ See the c++ class [std::set](https://en.cppreference.com/w/cpp/container/set) fo #define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy -#define i_cmp_functor // advanced, see examples/cpque.c for similar usage. +#define i_cmp_functor // advanced, see examples/functor.c for similar usage. #define i_tag // alternative typename: csset_{i_tag}. i_tag defaults to i_val #include ``` diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index 9cdbc9e5..9ff83be5 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -60,23 +60,23 @@ #define _c_RSEQ_N 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 #define _c_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, \ _14, _15, _16, N, ...) N - -#define c_STATIC_ASSERT(cond, msg) \ - ((void)sizeof(int[(cond) ? 1 : -1])) +/* Cast result to (void) to depress -Wall warning: */ +#define c_STATIC_ASSERT(cond, ...) \ + ((int)(0*sizeof(int[(cond) ? 1 : -1]))) #define c_CONTAINER_OF(p, T, m) \ ((T*)((char*)(p) + 0*sizeof((p) == &((T*)0)->m) - offsetof(T, m))) -#ifndef __cplusplus - #define c_ALLOC(T) c_MALLOC(sizeof(T)) - #define c_ALLOC_N(T, n) c_MALLOC(sizeof(T)*(n)) - #define c_NEW(T, ...) ((T*)memcpy(c_ALLOC(T), (T[]){__VA_ARGS__}, sizeof(T))) - #define c_INIT(T) (T) -#else +#ifdef __cplusplus #include #define c_ALLOC(T) static_cast(c_MALLOC(sizeof(T))) #define c_ALLOC_N(T, n) static_cast(c_MALLOC(sizeof(T)*(n))) #define c_NEW(T, ...) new (c_ALLOC(T)) T(__VA_ARGS__) #define c_INIT(T) T +#else + #define c_ALLOC(T) ((T*)c_MALLOC(sizeof(T))) + #define c_ALLOC_N(T, n) ((T*)c_MALLOC(sizeof(T)*(n))) + #define c_NEW(T, ...) ((T*)memcpy(c_ALLOC(T), (T[]){__VA_ARGS__}, sizeof(T))) + #define c_INIT(T) (T) #endif #ifndef c_MALLOC #define c_MALLOC(sz) malloc(sz) diff --git a/misc/examples/cpque.c b/misc/examples/cpque.c deleted file mode 100644 index 2ec841ae..00000000 --- a/misc/examples/cpque.c +++ /dev/null @@ -1,72 +0,0 @@ -// Implements c++ example: https://en.cppreference.com/w/cpp/container/priority_queue -// Example of per-instance less-function on a single priority queue type -// -// Note: i_less_functor: available for cpque types -// i_cmp_functor: available for csmap and csset types -// i_hash_functor/i_eq_functor: available for cmap and cset types - -#include -#include -#include -#include -#include - -// predeclare -forward_cpque(ipque, int); - -struct { - ipque Q; - bool (*less)(const int*, const int*); -} typedef IPQueue; - -#define IPQueue_drop(q) ipque_drop(&(q)->Q) - -#define i_type ipque -#define i_val int -#define i_opt c_is_forward // needed to avoid re-type-define container type -#define i_less_functor(self, x, y) c_CONTAINER_OF(self, IPQueue, Q)->less(x, y) // <== This. -#include - -#define print(name, q, n) do { \ - printf("%s: \t", name); \ - c_FORRANGE (i, n) printf("%d ", q[i]); \ - puts(""); \ -} while(0) - -void print_queue(const char* name, IPQueue q) { - // NB: make a clone because there is no way to traverse - // priority_queue's content without erasing the queue. - IPQueue copy = {ipque_clone(q.Q), q.less}; - - for (printf("%s: \t", name); !ipque_empty(©.Q); ipque_pop(©.Q)) - printf("%d ", *ipque_top(©.Q)); - puts(""); - ipque_drop(©.Q); -} - -static bool int_less(const int* x, const int* y) { return *x < *y; } -static bool int_greater(const int* x, const int* y) { return *x > *y; } -static bool int_lambda(const int* x, const int* y) { return (*x ^ 1) < (*y ^ 1); } - -int main() -{ - const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_ARRAYLEN(data); - print("data", data, n); - - c_AUTODROP (IPQueue, q1, {ipque_init(), int_less}) // Max priority queue - c_AUTODROP (IPQueue, minq1, {ipque_init(), int_greater}) // Min priority queue - c_AUTODROP (IPQueue, q5, {ipque_init(), int_lambda}) // Using lambda to compare elements. - { - c_FORRANGE (i, n) - ipque_push(&q1.Q, data[i]); - print_queue("q1", q1); - - c_FORRANGE (i, n) - ipque_push(&minq1.Q, data[i]); - print_queue("minq1", minq1); - - c_FORRANGE (i, n) - ipque_push(&q5.Q, data[i]); - print_queue("q5", q5); - } -} diff --git a/misc/examples/functor.c b/misc/examples/functor.c new file mode 100644 index 00000000..54e2702d --- /dev/null +++ b/misc/examples/functor.c @@ -0,0 +1,68 @@ +// Implements c++ example: https://en.cppreference.com/w/cpp/container/priority_queue +// Example of per-instance less-function on a single priority queue type +// +// Note: i_less_functor: available for cpque types only +// i_cmp_functor: available for csmap and csset types only +// i_hash_functor/i_eq_functor: available for cmap and cset types only + +#include +#include +#include +#include +#include + +// predeclare +forward_cpque(ipque, int); + +struct { + ipque Q; + bool (*less)(const int*, const int*); +} typedef IPQueue; + + +#define i_type ipque +#define i_val int +#define i_opt c_is_forward // needed to avoid re-type-define container type +#define i_less_functor(self, x, y) c_CONTAINER_OF(self, IPQueue, Q)->less(x, y) +#include + +void print_queue(const char* name, IPQueue q) { + // NB: make a clone because there is no way to traverse + // priority_queue's content without erasing the queue. + IPQueue copy = {ipque_clone(q.Q), q.less}; + + for (printf("%s: \t", name); !ipque_empty(©.Q); ipque_pop(©.Q)) + printf("%d ", *ipque_top(©.Q)); + puts(""); + ipque_drop(©.Q); +} + +static bool int_less(const int* x, const int* y) { return *x < *y; } +static bool int_greater(const int* x, const int* y) { return *x > *y; } +static bool int_lambda(const int* x, const int* y) { return (*x ^ 1) < (*y ^ 1); } + +int main() +{ + const int data[] = {1,8,5,6,3,4,0,9,7,2}, n = c_ARRAYLEN(data); + printf("data: \t"); + c_FORRANGE (i, n) printf("%d ", data[i]); + puts(""); + + IPQueue q1 = {ipque_init(), int_less}; // Max priority queue + IPQueue minq1 = {ipque_init(), int_greater}; // Min priority queue + IPQueue q5 = {ipque_init(), int_lambda}; // Using lambda to compare elements. + c_DEFER (ipque_drop(&q1.Q), ipque_drop(&minq1.Q), ipque_drop(&q5.Q)) + { + c_FORRANGE (i, n) + ipque_push(&q1.Q, data[i]); + print_queue("q1", q1); + + c_FORRANGE (i, n) + ipque_push(&minq1.Q, data[i]); + print_queue("minq1", minq1); + + c_FORRANGE (i, n) + ipque_push(&q5.Q, data[i]); + print_queue("q5", q5); + } +} diff --git a/misc/examples/intrusive.c b/misc/examples/intrusive.c index 4135317e..a0ac6095 100644 --- a/misc/examples/intrusive.c +++ b/misc/examples/intrusive.c @@ -2,51 +2,54 @@ #include -#define i_type List1 +#define i_type Inner #define i_val int -#define i_extern // implement List1_sort() +#define i_extern // implement Inner_sort() #include -#define i_type List2 -#define i_val List1_node +#define i_type Outer +#define i_val Inner_node #define i_opt c_no_cmp // no elem. comparison -#include +#include + +void printLists(Inner inner, Outer outer) { + printf("inner:"); + c_FOREACH (i, Inner, inner) + printf(" %d", *i.ref); + + printf("\nouter:"); + c_FOREACH (i, Outer, outer) + printf(" %d", i.ref->value); + puts(""); +} int main() { - c_AUTO (List2, list2) + c_AUTO (Outer, outer) { - List1 list1 = List1_init(); // should not be destroyed, list2 will destroy shared nodes. + Inner inner = Inner_init(); // do not destroy, outer will destroy the shared nodes. c_FORLIST (i, int, {6, 9, 3, 1, 7, 4, 5, 2, 8}) - List2_push_back(&list2, (List1_node){NULL, *i.ref}); + Outer_push_back(&outer, (Inner_node){NULL, *i.ref}); + + c_FOREACH (i, Outer, outer) + Inner_push_node_back(&inner, c_CONTAINER_OF(&i.ref->value, Inner_node, value)); - c_FOREACH (i, List2, list2) - List1_push_node_back(&list1, c_CONTAINER_OF(&i.ref->value, List1_node, value)); + printLists(inner, outer); - printf("list1:"); - c_FOREACH (i, List1, list1) printf(" %d", *i.ref); - printf("\nlist2:"); - c_FOREACH (i, List2, list2) printf(" %d", i.ref->value); + puts("sort inner"); + Inner_sort(&inner); - printf("\nsort list1"); - List1_sort(&list1); + printLists(inner, outer); - printf("\nlist1:"); - c_FOREACH (i, List1, list1) printf(" %d", *i.ref); - printf("\nlist2:"); - c_FOREACH (i, List2, list2) printf(" %d", i.ref->value); + puts("remove 5 from both lists in O(1) time"); + Inner_iter it1 = Inner_find(&inner, 5); - printf("\nremove 5 from both lists in O(1) time"); - List1_iter it1 = List1_find(&list1, 5); if (it1.ref) { - List1_unlink_node_after(&list1, it1.prev); - free(List2_unlink_node_after(&list2, c_CONTAINER_OF(it1.prev, List2_node, value))); + Inner_unlink_node_after(&inner, it1.prev); + free(Outer_unlink_node_after(&outer, c_CONTAINER_OF(it1.prev, Outer_node, value))); } - printf("\nlist1:"); - c_FOREACH (i, List1, list1) printf(" %d", *i.ref); - printf("\nlist2:"); - c_FOREACH (i, List2, list2) printf(" %d", i.ref->value); - puts(""); + + printLists(inner, outer); } } -- cgit v1.2.3