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. --- misc/examples/cpque.c | 72 ----------------------------------------------- misc/examples/functor.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ misc/examples/intrusive.c | 61 ++++++++++++++++++++------------------- 3 files changed, 100 insertions(+), 101 deletions(-) delete mode 100644 misc/examples/cpque.c create mode 100644 misc/examples/functor.c (limited to 'misc') 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