diff options
| author | Tyge Lovset <[email protected]> | 2022-12-20 23:31:51 +0100 |
|---|---|---|
| committer | Tyge Lovset <[email protected]> | 2022-12-20 23:31:51 +0100 |
| commit | 5f57d597cd27aef55adbcb3b452973b0c6e33667 (patch) | |
| tree | dfd59c2fd0e36a6ef37912a9d0cc5a65970f1524 /misc/examples | |
| parent | 1763be8c8cbbc0896477fcf924edd4180d1345a9 (diff) | |
| download | STC-modified-5f57d597cd27aef55adbcb3b452973b0c6e33667.tar.gz STC-modified-5f57d597cd27aef55adbcb3b452973b0c6e33667.zip | |
Restructured folders: examples, benchmarks, tests into misc folder.
Diffstat (limited to 'misc/examples')
73 files changed, 4545 insertions, 0 deletions
diff --git a/misc/examples/README.md b/misc/examples/README.md new file mode 100644 index 00000000..4c0aa763 --- /dev/null +++ b/misc/examples/README.md @@ -0,0 +1,4 @@ +Examples +======== +This folder contains various examples of STC container usage. + diff --git a/misc/examples/arc_containers.c b/misc/examples/arc_containers.c new file mode 100644 index 00000000..b577f2c8 --- /dev/null +++ b/misc/examples/arc_containers.c @@ -0,0 +1,79 @@ +// Create a stack and a list of shared pointers to maps, +// and demonstrate sharing and cloning of maps. +#define i_static +#include <stc/cstr.h> +#define i_type Map +#define i_key_str // strings +#define i_val int +#define i_keydrop(p) (printf("drop name: %s\n", cstr_str(p)), cstr_drop(p)) +#include <stc/csmap.h> + +#define i_type Arc // (atomic) ref. counted type +#define i_val Map +#define i_valdrop(p) (printf("drop Arc:\n"), Map_drop(p)) +// no need for atomic ref. count in single thread: +#define i_opt c_no_atomic|c_no_lookup +#include <stc/carc.h> + +#define i_type Stack +#define i_valboxed Arc // define i_valboxed for carc/cbox value (not i_val) +#define i_opt c_no_cmp +#include <stc/cvec.h> + +#define i_type List +#define i_valboxed Arc // as above +#define i_opt c_no_cmp +#include <stc/clist.h> + +int main() +{ + c_auto (Stack, stack) + c_auto (List, list) + { + // POPULATE stack with shared pointers to Maps: + Map *map; + map = Stack_push(&stack, Arc_from(Map_init()))->get; + Map_emplace(map, "Joey", 1990); + Map_emplace(map, "Mary", 1995); + Map_emplace(map, "Joanna", 1992); + + map = Stack_push(&stack, Arc_from(Map_init()))->get; + Map_emplace(map, "Rosanna", 2001); + Map_emplace(map, "Brad", 1999); + Map_emplace(map, "Jack", 1980); + + // POPULATE list: + map = List_push_back(&list, Arc_from(Map_init()))->get; + Map_emplace(map, "Steve", 1979); + Map_emplace(map, "Rick", 1974); + Map_emplace(map, "Tracy", 2003); + + // Share two Maps from the stack with the list using emplace (clone the carc): + List_push_back(&list, Arc_clone(stack.data[0])); + List_push_back(&list, Arc_clone(stack.data[1])); + + // Clone (deep copy) a Map from the stack to the list + // List will contain two shared and two unshared maps. + map = List_push_back(&list, Arc_from(Map_clone(*stack.data[1].get)))->get; + + // Add one more element to the cloned map: + Map_emplace_or_assign(map, "CLONED", 2021); + + // Add one more element to the shared map: + Map_emplace_or_assign(stack.data[1].get, "SHARED", 2021); + + + puts("STACKS"); + c_foreach (i, Stack, stack) { + c_forpair (name, year, Map, *i.ref->get) + printf(" %s:%d", cstr_str(_.name), *_.year); + puts(""); + } + puts("LIST"); + c_foreach (i, List, list) { + c_forpair (name, year, Map, *i.ref->get) + printf(" %s:%d", cstr_str(_.name), *_.year); + puts(""); + } + } +} diff --git a/misc/examples/arc_demo.c b/misc/examples/arc_demo.c new file mode 100644 index 00000000..087f90ac --- /dev/null +++ b/misc/examples/arc_demo.c @@ -0,0 +1,56 @@ +#include <stdio.h> +#include <string.h> + +void int_drop(int* x) { + printf("drop: %d\n", *x); +} + +// carc implements its own clone method using reference counting, +// so 'i_valclone' is not required to be defined (ignored). + +#define i_type Arc // set type name to be defined (instead of 'carc_int') +#define i_val int +#define i_valdrop int_drop // optional, just to display the elements destroyed +#include <stc/carc.h> // Arc + +#define i_keyboxed Arc // note: use i_keyboxed instead of i_key for carc/cbox elements +#include <stc/csset.h> // csset_Arc (like: std::set<std::shared_ptr<int>>) + +#define i_valboxed Arc // note: as above. +#include <stc/cvec.h> // cvec_Arc (like: std::vector<std::shared_ptr<int>>) + +int main() +{ + c_auto (cvec_Arc, vec) // declare and init vec, call cvec_Arc_drop() at scope exit + c_auto (csset_Arc, set) // declare and init set, call csset_Arc_drop() at scope exit + { + const int years[] = {2021, 2012, 2022, 2015}; + c_forrange (i, c_arraylen(years)) + cvec_Arc_push(&vec, Arc_from(years[i])); + + printf("vec:"); + c_foreach (i, cvec_Arc, vec) printf(" %d", *i.ref->get); + puts(""); + + // add odd numbers from vec to set + c_foreach (i, cvec_Arc, vec) + if (*i.ref->get & 1) + csset_Arc_insert(&set, Arc_clone(*i.ref)); // copy shared pointer => increments counter. + + // erase the two last elements in vec + cvec_Arc_pop_back(&vec); + cvec_Arc_pop_back(&vec); + + printf("vec:"); + c_foreach (i, cvec_Arc, vec) printf(" %d", *i.ref->get); + + printf("\nset:"); + c_foreach (i, csset_Arc, set) printf(" %d", *i.ref->get); + + c_with (Arc p = Arc_clone(vec.data[0]), Arc_drop(&p)) { + printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count); + } + + puts("\nDone"); + } +} diff --git a/misc/examples/arcvec_erase.c b/misc/examples/arcvec_erase.c new file mode 100644 index 00000000..c70d59d9 --- /dev/null +++ b/misc/examples/arcvec_erase.c @@ -0,0 +1,53 @@ +#include <stdio.h> + +void show_drop(int* x) { printf("drop: %d\n", *x); } + +#define i_type Arc +#define i_val int +#define i_valdrop show_drop +#define i_cmp c_default_cmp // enable object comparisons (default ptr compare) +#include <stc/carc.h> // Shared pointer to int + +#define i_type Vec +#define i_valboxed Arc +#include <stc/cvec.h> // Vec: cvec<Arc> + + +int main() +{ + c_auto (Vec, vec) + { + c_forlist (i, int, {2012, 1990, 2012, 2019, 2015}) + Vec_emplace(&vec, *i.ref); + + // clone the second 2012 and push it back. + // note: cloning make sure that vec.data[2] has ref count 2. + Vec_push(&vec, Arc_clone(vec.data[2])); + + printf("vec before erase :"); + c_foreach (i, Vec, vec) + printf(" %d", *i.ref->get); + + printf("\nerase vec.data[2]; or first matching value depending on compare.\n"); + Vec_iter it; + it = Vec_find(&vec, *vec.data[2].get); + if (it.ref != Vec_end(&vec).ref) + Vec_erase_at(&vec, it); + + int year = 2015; + it = Vec_find(&vec, year); // Ok as tmp only. + if (it.ref != Vec_end(&vec).ref) + Vec_erase_at(&vec, it); + + printf("vec after erase :"); + c_foreach (i, Vec, vec) + printf(" %d", *i.ref->get); + + Vec_sort(&vec); + printf("\nvec after sort :"); + c_foreach (i, Vec, vec) + printf(" %d", *i.ref->get); + + puts("\nDone"); + } +} diff --git a/misc/examples/astar.c b/misc/examples/astar.c new file mode 100644 index 00000000..d4a821f9 --- /dev/null +++ b/misc/examples/astar.c @@ -0,0 +1,166 @@ +// +// -- An A* pathfinder inspired by the excellent tutorial at Red Blob Games -- +// +// This is a reimplementation of the CTL example to STC: +// https://github.com/glouw/ctl/blob/master/examples/astar.c +// https://www.redblobgames.com/pathfinding/a-star/introduction.html +#include <stc/cstr.h> +#include <stdio.h> + +typedef struct +{ + int x; + int y; + int priorty; + int width; +} +point; + +point +point_init(int x, int y, int width) +{ + return (point) { x, y, 0, width }; +} + +int +point_cmp_priority(const point* a, const point* b) +{ + return c_default_cmp(&a->priorty, &b->priorty); +} + +int +point_equal(const point* a, const point* b) +{ + return a->x == b->x && a->y == b->y; +} + +point +point_from(const cstr* maze, const char* c, int width) +{ + int index = cstr_find(maze, c); + return point_init(index % width, index / width, width); +} + +int +point_index(const point* p) +{ + return p->x + p->width * p->y; +} + +int +point_key_cmp(const point* a, const point* b) +{ + int i = point_index(a); + int j = point_index(b); + return (i == j) ? 0 : (i < j) ? -1 : 1; +} + +#define i_val point +#define i_cmp point_cmp_priority +#include <stc/cpque.h> + +#define i_val point +#define i_opt c_no_cmp +#include <stc/cdeq.h> + +#define i_key point +#define i_val int +#define i_cmp point_key_cmp +#define i_tag pcost +#include <stc/csmap.h> + +#define i_key point +#define i_val point +#define i_cmp point_key_cmp +#define i_tag pstep +#include <stc/csmap.h> + +cdeq_point +astar(cstr* maze, int width) +{ + cdeq_point path = cdeq_point_init(); + + c_auto (cpque_point, front) + c_auto (csmap_pstep, from) + c_auto (csmap_pcost, costs) + { + point start = point_from(maze, "@", width); + point goal = point_from(maze, "!", width); + csmap_pcost_insert(&costs, start, 0); + cpque_point_push(&front, start); + while (!cpque_point_empty(&front)) + { + point current = *cpque_point_top(&front); + cpque_point_pop(&front); + if (point_equal(¤t, &goal)) + break; + point deltas[] = { + { -1, +1, 0, width }, { 0, +1, 0, width }, { 1, +1, 0, width }, + { -1, 0, 0, width }, /* ~ ~ ~ ~ ~ ~ ~ */ { 1, 0, 0, width }, + { -1, -1, 0, width }, { 0, -1, 0, width }, { 1, -1, 0, width }, + }; + for (size_t i = 0; i < c_arraylen(deltas); i++) + { + point delta = deltas[i]; + point next = point_init(current.x + delta.x, current.y + delta.y, width); + int new_cost = *csmap_pcost_at(&costs, current); + if (cstr_str(maze)[point_index(&next)] != '#') + { + const csmap_pcost_value *cost = csmap_pcost_get(&costs, next); + if (cost == NULL || new_cost < cost->second) + { + csmap_pcost_insert(&costs, next, new_cost); + next.priorty = new_cost + abs(goal.x - next.x) + abs(goal.y - next.y); + cpque_point_push(&front, next); + csmap_pstep_insert(&from, next, current); + } + } + } + } + point current = goal; + while (!point_equal(¤t, &start)) + { + cdeq_point_push_front(&path, current); + current = *csmap_pstep_at(&from, current); + } + cdeq_point_push_front(&path, start); + } + return path; +} + +int +main(void) +{ + c_with (cstr maze = cstr_lit( + "#########################################################################\n" + "# # # # # # #\n" + "# # ######### # ##### ######### ##### ##### ##### # ! #\n" + "# # # # # # # # # #\n" + "######### # ######### ######### ##### # # # ######### #\n" + "# # # # # # # # # # #\n" + "# # ############# # # ######### ##### # ######### # #\n" + "# # # # # # # # # #\n" + "# ############# ##### ##### # ##### ######### # ##### #\n" + "# # # # # # # # # #\n" + "# ##### ##### # ##### # ######### # # # #############\n" + "# # # # # # # # # # # #\n" + "############# # # # ######### # ##### # ##### ##### #\n" + "# # # # # # # # # #\n" + "# ##### # ######### ##### # ##### ##### ############# #\n" + "# # # # # # # # # #\n" + "# # ######### # ##### ######### # # ############# # #\n" + "# # # # # # # # # # #\n" + "# ######### # # # ##### ######### ######### # #########\n" + "# # # # # # # # # #\n" + "# @ # ##### ##### ##### ######### ##### # ######### # #\n" + "# # # # # # #\n" + "#########################################################################\n"), cstr_drop(&maze)) + { + int width = cstr_find(&maze, "\n") + 1; + c_with (cdeq_point path = astar(&maze, width), cdeq_point_drop(&path)) + { + c_foreach (it, cdeq_point, path) cstr_data(&maze)[point_index(it.ref)] = 'x'; + printf("%s", cstr_str(&maze)); + } + } +} diff --git a/misc/examples/birthday.c b/misc/examples/birthday.c new file mode 100644 index 00000000..48b8ceaa --- /dev/null +++ b/misc/examples/birthday.c @@ -0,0 +1,68 @@ +#include <math.h> +#include <stdio.h> +#include <time.h> +#include <stc/crandom.h> + +#define i_tag ic +#define i_key uint64_t +#define i_val uint8_t +#include <stc/cmap.h> + +static uint64_t seed = 12345; + +static void test_repeats(void) +{ + enum {BITS = 46, BITS_TEST = BITS/2 + 2}; + const static uint64_t N = 1ull << BITS_TEST; + const static uint64_t mask = (1ull << BITS) - 1; + + printf("birthday paradox: value range: 2^%d, testing repeats of 2^%d values\n", BITS, BITS_TEST); + stc64_t rng = stc64_new(seed); + c_auto (cmap_ic, m) + { + cmap_ic_reserve(&m, N); + c_forrange (i, N) { + uint64_t k = stc64_rand(&rng) & mask; + int v = cmap_ic_insert(&m, k, 0).ref->second += 1; + if (v > 1) printf("repeated value %" PRIu64 " (%d) at 2^%d\n", + k, v, (int) log2((double) i)); + } + } +} + +#define i_key uint32_t +#define i_val uint64_t +#define i_tag x +#include <stc/cmap.h> + +void test_distribution(void) +{ + enum {BITS = 26}; + printf("distribution test: 2^%d values\n", BITS); + stc64_t rng = stc64_new(seed); + const size_t N = 1ull << BITS ; + + c_auto (cmap_x, map) { + c_forrange (N) { + uint64_t k = stc64_rand(&rng); + cmap_x_insert(&map, k & 0xf, 0).ref->second += 1; + } + + uint64_t sum = 0; + c_foreach (i, cmap_x, map) sum += i.ref->second; + sum /= map.size; + + c_foreach (i, cmap_x, map) { + printf("%4" PRIu32 ": %" PRIu64 " - %" PRIu64 ": %11.8f\n", + i.ref->first, i.ref->second, sum, + (1 - (double)i.ref->second / sum)); + } + } +} + +int main() +{ + seed = time(NULL); + test_distribution(); + test_repeats(); +} diff --git a/misc/examples/bits.c b/misc/examples/bits.c new file mode 100644 index 00000000..82fd65ec --- /dev/null +++ b/misc/examples/bits.c @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <stc/cbits.h> + +int main() +{ + c_with (cbits set = cbits_with_size(23, true), cbits_drop(&set)) { + printf("count %" c_ZU ", %" c_ZU "\n", cbits_count(&set), cbits_size(&set)); + cbits s1 = cbits_from("1110100110111"); + char buf[256]; + cbits_to_str(&s1, buf, 0, 255); + printf("buf: %s: %" c_ZU "\n", buf, cbits_count(&s1)); + cbits_drop(&s1); + + cbits_reset(&set, 9); + cbits_resize(&set, 43, false); + printf(" str: %s\n", cbits_to_str(&set, buf, 0, 255)); + + printf("%4" c_ZU ": ", cbits_size(&set)); + c_forrange (i, cbits_size(&set)) + printf("%d", cbits_test(&set, i)); + puts(""); + + cbits_set(&set, 28); + cbits_resize(&set, 77, true); + cbits_resize(&set, 93, false); + cbits_resize(&set, 102, true); + cbits_set_value(&set, 99, false); + printf("%4" c_ZU ": ", cbits_size(&set)); + c_forrange (i, cbits_size(&set)) + printf("%d", cbits_test(&set, i)); + + puts("\nIterate:"); + printf("%4" c_ZU ": ", cbits_size(&set)); + c_forrange (i, cbits_size(&set)) + printf("%d", cbits_test(&set, i)); + puts(""); + + c_with (cbits s2 = cbits_clone(set), cbits_drop(&s2)) { + cbits_flip_all(&s2); + cbits_set(&s2, 16); + cbits_set(&s2, 17); + cbits_set(&s2, 18); + printf(" new: "); + c_forrange (i, cbits_size(&s2)) + printf("%d", cbits_test(&s2, i)); + puts(""); + + printf(" xor: "); + cbits_xor(&set, &s2); + c_forrange (i, cbits_size(&set)) + printf("%d", cbits_test(&set, i)); + puts(""); + + cbits_set_all(&set, false); + printf("%4" c_ZU ": ", cbits_size(&set)); + c_forrange (i, cbits_size(&set)) + printf("%d", cbits_test(&set, i)); + puts(""); + } + } +} diff --git a/misc/examples/bits2.c b/misc/examples/bits2.c new file mode 100644 index 00000000..59e0b337 --- /dev/null +++ b/misc/examples/bits2.c @@ -0,0 +1,41 @@ +#include <stdio.h> +// Example of static sized (stack allocated) bitsets + +#define i_type Bits +#define i_capacity 80 // enable fixed bitset on the stack +#include <stc/cbits.h> + +int main() +{ + Bits s1 = Bits_from("1110100110111"); + + printf("size %" c_ZU "\n", Bits_size(&s1)); + char buf[256]; + Bits_to_str(&s1, buf, 0, 256); + printf("buf: %s: count=%" c_ZU "\n", buf, Bits_count(&s1)); + + Bits_reset(&s1, 8); + printf(" s1: %s\n", Bits_to_str(&s1, buf, 0, 256)); + + Bits s2 = Bits_clone(s1); + + Bits_flip_all(&s2); + Bits_reset(&s2, 66); + Bits_reset(&s2, 67); + printf(" s2: "); + c_forrange (i, Bits_size(&s2)) + printf("%d", Bits_test(&s2, i)); + puts(""); + + printf("xor: "); + Bits_xor(&s1, &s2); + c_forrange (i, Bits_size(&s1)) + printf("%d", Bits_test(&s1, i)); + puts(""); + + printf("all: "); + Bits_set_pattern(&s1, 0x3333333333333333); + c_forrange (i, Bits_size(&s1)) + printf("%d", Bits_test(&s1, i)); + puts(""); +} diff --git a/misc/examples/books.c b/misc/examples/books.c new file mode 100644 index 00000000..b6067d81 --- /dev/null +++ b/misc/examples/books.c @@ -0,0 +1,60 @@ +// https://doc.rust-lang.org/std/collections/struct.HashMap.html +#include <stc/cstr.h> +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +// Type inference lets us omit an explicit type signature (which +// would be `HashMap<String, String>` in this example). +int main() +{ + c_auto (cmap_str, book_reviews) + { + // Review some books. + cmap_str_emplace(&book_reviews, + "Adventures of Huckleberry Finn", + "My favorite book." + ); + cmap_str_emplace(&book_reviews, + "Grimms' Fairy Tales", + "Masterpiece." + ); + cmap_str_emplace(&book_reviews, + "Pride and Prejudice", + "Very enjoyable" + ); + cmap_str_insert(&book_reviews, + cstr_lit("The Adventures of Sherlock Holmes"), + cstr_lit("Eye lyked it alot.") + ); + + // Check for a specific one. + // When collections store owned values (String), they can still be + // queried using references (&str). + if (cmap_str_contains(&book_reviews, "Les Misérables")) { + printf("We've got %" c_ZU " reviews, but Les Misérables ain't one.", + cmap_str_size(&book_reviews)); + } + + // oops, this review has a lot of spelling mistakes, let's delete it. + cmap_str_erase(&book_reviews, "The Adventures of Sherlock Holmes"); + + // Look up the values associated with some keys. + const char* to_find[] = {"Pride and Prejudice", "Alice's Adventure in Wonderland"}; + c_forrange (i, c_arraylen(to_find)) { + const cmap_str_value* b = cmap_str_get(&book_reviews, to_find[i]); + if (b) + printf("%s: %s\n", cstr_str(&b->first), cstr_str(&b->second)); + else + printf("%s is unreviewed.\n", to_find[i]); + } + + // Look up the value for a key (will panic if the key is not found). + printf("Review for Jane: %s\n", cstr_str(cmap_str_at(&book_reviews, "Pride and Prejudice"))); + + // Iterate over everything. + c_forpair (book, review, cmap_str, book_reviews) { + printf("%s: \"%s\"\n", cstr_str(_.book), cstr_str(_.review)); + } + } +} diff --git a/misc/examples/box.c b/misc/examples/box.c new file mode 100644 index 00000000..da13501f --- /dev/null +++ b/misc/examples/box.c @@ -0,0 +1,68 @@ +/* cbox: heap allocated boxed type */ +#include <stc/cstr.h> + +typedef struct { cstr name, last; } Person; + +Person Person_make(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} + +uint64_t Person_hash(const Person* a) { + return cstr_hash(&a->name) ^ cstr_hash(&a->last); +} + +int Person_cmp(const Person* a, const Person* b) { + int c = cstr_cmp(&a->name, &b->name); + return c ? c : cstr_cmp(&a->last, &b->last); +} + +Person Person_clone(Person p) { + p.name = cstr_clone(p.name); + p.last = cstr_clone(p.last); + return p; +} + +void Person_drop(Person* p) { + printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last)); + c_drop(cstr, &p->name, &p->last); +} + +#define i_type PBox +#define i_valclass Person // "class" binds _cmp, _clone, _drop functions. +#include <stc/cbox.h> + +#define i_type Persons +#define i_valboxed PBox // "arcbox" informs that PBox is a smart pointer. +#include <stc/csset.h> + +int main() +{ + c_auto (Persons, vec) + c_auto (PBox, p, q) + { + p = PBox_from(Person_make("Laura", "Palmer")); + q = PBox_clone(p); + cstr_assign(&q.get->name, "Leland"); + + printf("orig: %s %s\n", cstr_str(&p.get->name), cstr_str(&p.get->last)); + printf("copy: %s %s\n", cstr_str(&q.get->name), cstr_str(&q.get->last)); + + Persons_emplace(&vec, Person_make("Dale", "Cooper")); + Persons_emplace(&vec, Person_make("Audrey", "Home")); + + // NB! Clone/share p and q in the Persons container. + Persons_push(&vec, PBox_clone(p)); + Persons_push(&vec, PBox_clone(q)); + + c_foreach (i, Persons, vec) + printf("%s %s\n", cstr_str(&i.ref->get->name), cstr_str(&i.ref->get->last)); + puts(""); + + // Look-up Audrey! Create a temporary Person for lookup. + c_with (Person a = Person_make("Audrey", "Home"), Person_drop(&a)) { + const PBox *v = Persons_get(&vec, a); // lookup + if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last)); + } + puts(""); + } +} diff --git a/misc/examples/box2.c b/misc/examples/box2.c new file mode 100644 index 00000000..b9628eeb --- /dev/null +++ b/misc/examples/box2.c @@ -0,0 +1,90 @@ +// https://doc.rust-lang.org/rust-by-example/std/box.html + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stc/ccommon.h> + +struct { + double x; + double y; +} typedef Point; + +// A Rectangle can be specified by where its top left and bottom right +// corners are in space +struct { + Point top_left; + Point bottom_right; +} typedef Rectangle; + +#define i_val Point +#define i_opt c_no_lookup +#include <stc/cbox.h> // cbox_Point + +#define i_val Rectangle +#define i_opt c_no_lookup +#include <stc/cbox.h> // cbox_Rectangle + +// Box in box: +#define i_valboxed cbox_Point // NB: use i_valboxed when value is a cbox or carc! + // it will auto define i_valdrop, i_valfrom, and i_cmp. +#define i_tag BoxPoint +#define i_opt c_no_lookup +#include <stc/cbox.h> // cbox_BoxPoint + +Point origin(void) { + return (Point){ .x=1.0, .y=2.0 }; +} + +cbox_Point boxed_origin(void) { + // Allocate this point on the heap, and return a pointer to it + return cbox_Point_make((Point){ .x=2.0, .y=3.0 }); +} + + +int main(void) { + // Stack allocated variables + Point point = origin(); + Rectangle rectangle = (Rectangle){ + .top_left = origin(), + .bottom_right = (Point){ .x=3.0, .y=-4.0 } + }; + + // Declare auto-deleted box objects + c_auto (cbox_Rectangle, boxed_rectangle) + c_auto (cbox_Point, boxed_point) + c_auto (cbox_BoxPoint, box_in_a_box, boxbox2) + { + // Heap allocated rectangle + boxed_rectangle = cbox_Rectangle_make((Rectangle){ + .top_left = origin(), + .bottom_right = (Point){ .x=3.0, .y=-4.0 } + }); + + // The output of functions can be boxed + boxed_point = cbox_Point_from(origin()); + + // Double indirection + box_in_a_box = cbox_BoxPoint_make(boxed_origin()); + boxbox2 = cbox_BoxPoint_from(point); // !! + printf("boxbox2: x=%f\n", boxbox2.get->get->x); + + printf("Point occupies %" c_ZU " bytes on the stack\n", + sizeof(point)); + printf("Rectangle occupies %" c_ZU " bytes on the stack\n", + sizeof(rectangle)); + + // box size == pointer size + printf("Boxed point occupies %" c_ZU " bytes on the stack\n", + sizeof(boxed_point)); + printf("Boxed rectangle occupies %" c_ZU " bytes on the stack\n", + sizeof(boxed_rectangle)); + printf("Boxed box occupies %" c_ZU " bytes on the stack\n", + sizeof(box_in_a_box)); + + // Copy the data contained in `boxed_point` into `unboxed_point` + Point unboxed_point = *boxed_point.get; + printf("Unboxed point occupies %" c_ZU " bytes on the stack\n", + sizeof(unboxed_point)); + } +} diff --git a/misc/examples/city.c b/misc/examples/city.c new file mode 100644 index 00000000..8557c6cf --- /dev/null +++ b/misc/examples/city.c @@ -0,0 +1,91 @@ +#include <stc/cstr.h> + +typedef struct { + cstr name; + cstr country; + float lat, lon; + int population; +} City; + +int City_cmp(const City* a, const City* b); +uint64_t City_hash(const City* a); +City City_clone(City c); +void City_drop(City* c); + +#define i_type CityArc +#define i_valclass City +#include <stc/cbox.h> +//#include <stc/carc.h> // try instead of cbox.h + +#define i_type Cities +#define i_keyboxed CityArc +#include <stc/cvec.h> + +#define i_type CityMap +#define i_key int +#define i_valboxed CityArc +#include <stc/csmap.h> + + +int City_cmp(const City* a, const City* b) { + int c = cstr_cmp(&a->name, &b->name); + return c ? c : cstr_cmp(&a->country, &b->country); +} + +uint64_t City_hash(const City* a) { + return cstr_hash(&a->name) ^ cstr_hash(&a->country); +} + +City City_clone(City c) { + c.name = cstr_clone(c.name); + c.country = cstr_clone(c.country); + return c; +} + +void City_drop(City* c) { + printf("drop %s\n", cstr_str(&c->name)); + c_drop(cstr, &c->name, &c->country); +} + + +int main(void) +{ + c_auto (Cities, cities, copy) + c_auto (CityMap, map) + { + c_forlist (i, City, { + {cstr_lit("New York"), cstr_lit("US"), 4.3f, 23.2f, 9000000}, + {cstr_lit("Paris"), cstr_lit("France"), 4.3f, 23.2f, 9000000}, + {cstr_lit("Berlin"), cstr_lit("Germany"), 4.3f, 23.2f, 9000000}, + {cstr_lit("London"), cstr_lit("UK"), 4.3f, 23.2f, 9000000}, + }) Cities_emplace(&cities, *i.ref); // NB. creates smart pointers! + + Cities_sort(&cities); + + printf("Vec:\n"); + c_foreach (c, Cities, cities) + printf("city:%s, %d, use:%ld\n", cstr_str(&c.ref->get->name), + c.ref->get->population, + CityArc_use_count(c.ref)); + puts(""); + copy = Cities_clone(cities); // share each element! + + int k = 0, id[] = {8, 4, 3, 9, 2, 5}; + c_foreach (i, Cities, cities) + CityMap_insert(&map, id[k++], CityArc_clone(*i.ref)); + + Cities_pop(&cities); + Cities_pop(&cities); + + printf("Vec:\n"); + c_foreach (c, Cities, cities) + printf("city:%s, %d, use:%ld\n", cstr_str(&c.ref->get->name), + c.ref->get->population, + CityArc_use_count(c.ref)); + printf("\nMap:\n"); + c_forpair (id, city, CityMap, map) + printf("id:%d, city:%s, %d, use:%ld\n", *_.id, cstr_str(&_.city->get->name), + _.city->get->population, CityArc_use_count(_.city)); + puts(""); + } +} diff --git a/misc/examples/complex.c b/misc/examples/complex.c new file mode 100644 index 00000000..dd2f951a --- /dev/null +++ b/misc/examples/complex.c @@ -0,0 +1,55 @@ + +// Define similar c++ data types: +// +// using FloatStack = std::stack<float>; +// using StackList = std::stack<FloatStack>; +// using ListMap = std::unordered_map<int, std::forward_list<StackList>>; +// using MapMap = std::unordered_map<std::string, ListMap>; + +#include <stc/cstr.h> + + +#define i_type FloatStack +#define i_val float +#include <stc/cstack.h> + +#define i_type StackList +#define i_valclass FloatStack // "class" picks up _clone, _drop +#define i_opt c_no_cmp // no FloatStack_cmp() +#include <stc/clist.h> + +#define i_type ListMap +#define i_key int +#define i_valclass StackList // "class" picks up _clone, _drop +#include <stc/cmap.h> + +#define i_type MapMap +#define i_key_str +#define i_valclass ListMap +#include <stc/cmap.h> + + +int main() +{ + c_auto (MapMap, mmap) + { + FloatStack stack = FloatStack_with_size(10, 0); + + // Put in some data in the structures + stack.data[3] = 3.1415927f; + printf("stack size: %" c_ZU "\n", FloatStack_size(&stack)); + + StackList list = StackList_init(); + StackList_push_back(&list, stack); + + ListMap lmap = ListMap_init(); + ListMap_insert(&lmap, 42, list); + MapMap_insert(&mmap, cstr_from("first"), lmap); + + // Access the data entry + const ListMap* lmap_p = MapMap_at(&mmap, "first"); + const StackList* list_p = ListMap_at(lmap_p, 42); + const FloatStack* stack_p = StackList_back(list_p); + printf("value is: %f\n", *FloatStack_at(stack_p, 3)); // pi + } +} diff --git a/misc/examples/convert.c b/misc/examples/convert.c new file mode 100644 index 00000000..18be3c81 --- /dev/null +++ b/misc/examples/convert.c @@ -0,0 +1,50 @@ +#include <stc/cstr.h> + +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +#define i_val_str +#include <stc/cvec.h> + +#define i_val_str +#define i_extern // define _clist_mergesort() once +#include <stc/clist.h> + +int main() +{ + c_auto (cmap_str, map, mclone) + c_auto (cvec_str, keys, values) + c_auto (clist_str, list) + { + c_forlist (i, cmap_str_raw, { + {"green", "#00ff00"}, + {"blue", "#0000ff"}, + {"yellow", "#ffff00"}, + }) cmap_str_emplace(&map, c_PAIR(i.ref)); + + puts("MAP:"); + c_foreach (i, cmap_str, map) + printf(" %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + + puts("\nCLONE MAP:"); + mclone = cmap_str_clone(map); + c_foreach (i, cmap_str, mclone) + printf(" %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + + puts("\nCOPY MAP TO VECS:"); + c_foreach (i, cmap_str, mclone) { + cvec_str_emplace_back(&keys, cstr_str(&i.ref->first)); + cvec_str_emplace_back(&values, cstr_str(&i.ref->second)); + } + c_forrange (i, cvec_str_size(&keys)) + printf(" %s: %s\n", cstr_str(keys.data + i), cstr_str(values.data + i)); + + puts("\nCOPY VEC TO LIST:"); + c_foreach (i, cvec_str, keys) + clist_str_emplace_back(&list, cstr_str(i.ref)); + + c_foreach (i, clist_str, list) + printf(" %s\n", cstr_str(i.ref)); + } +} diff --git a/misc/examples/cpque.c b/misc/examples/cpque.c new file mode 100644 index 00000000..7254b0f7 --- /dev/null +++ b/misc/examples/cpque.c @@ -0,0 +1,72 @@ +// 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 <stdio.h> +#include <stdbool.h> +#include <stc/forward.h> +#include <stc/views.h> +#include <stc/cstr.h> + +// 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 <stc/cpque.h> + +#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/csmap_erase.c b/misc/examples/csmap_erase.c new file mode 100644 index 00000000..48d8ceef --- /dev/null +++ b/misc/examples/csmap_erase.c @@ -0,0 +1,84 @@ +// map_erase.c +// From C++ example: https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-16 +#include <stc/cstr.h> +#include <stdio.h> + +#define i_key int +#define i_val_str +#define i_type mymap +#include <stc/csmap.h> + +void printmap(mymap m) +{ + c_foreach (elem, mymap, m) + printf(" [%d, %s]", elem.ref->first, cstr_str(&elem.ref->second)); + printf("\nsize() == %" c_ZU "\n\n", mymap_size(&m)); +} + +int main() +{ + c_auto (mymap, m1) + { + // Fill in some data to test with, one at a time + mymap_insert(&m1, 1, cstr_lit("A")); + mymap_insert(&m1, 2, cstr_lit("B")); + mymap_insert(&m1, 3, cstr_lit("C")); + mymap_insert(&m1, 4, cstr_lit("D")); + mymap_insert(&m1, 5, cstr_lit("E")); + + puts("Starting data of map m1 is:"); + printmap(m1); + // The 1st member function removes an element at a given position + mymap_erase_at(&m1, mymap_advance(mymap_begin(&m1), 1)); + puts("After the 2nd element is deleted, the map m1 is:"); + printmap(m1); + } + + c_auto (mymap, m2) + { + // Fill in some data to test with, one at a time + c_forlist (i, mymap_raw, { + {10, "Bob"}, + {11, "Rob"}, + {12, "Robert"}, + {13, "Bert"}, + {14, "Bobby"}, + }) mymap_emplace(&m2, c_PAIR(i.ref)); + + puts("Starting data of map m2 is:"); + printmap(m2); + mymap_iter it1 = mymap_advance(mymap_begin(&m2), 1); + mymap_iter it2 = mymap_find(&m2, mymap_back(&m2)->first); + + puts("to remove:"); + c_foreach (i, mymap, it1, it2) + printf(" [%d, %s]", i.ref->first, cstr_str(&i.ref->second)); + puts(""); + // The 2nd member function removes elements + // in the range [First, Last) + mymap_erase_range(&m2, it1, it2); + puts("After the middle elements are deleted, the map m2 is:"); + printmap(m2); + } + + c_auto (mymap, m3) + { + // Fill in some data to test with, one at a time, using emplace + mymap_emplace(&m3, 1, "red"); + mymap_emplace(&m3, 2, "yellow"); + mymap_emplace(&m3, 3, "blue"); + mymap_emplace(&m3, 4, "green"); + mymap_emplace(&m3, 5, "orange"); + mymap_emplace(&m3, 6, "purple"); + mymap_emplace(&m3, 7, "pink"); + + puts("Starting data of map m3 is:"); + printmap(m3); + // The 3rd member function removes elements with a given Key + size_t count = mymap_erase(&m3, 2); + // The 3rd member function also returns the number of elements removed + printf("The number of elements removed from m3 is: %" c_ZU "\n", count); + puts("After the element with a key of 2 is deleted, the map m3 is:"); + printmap(m3); + } +} diff --git a/misc/examples/csmap_find.c b/misc/examples/csmap_find.c new file mode 100644 index 00000000..3c507476 --- /dev/null +++ b/misc/examples/csmap_find.c @@ -0,0 +1,74 @@ +// This implements the c++ std::map::find example at: +// https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-17 +#include <stc/cstr.h> + +#define i_key int +#define i_val_str +#define i_tag istr +#include <stc/csmap.h> + +#define i_val csmap_istr_raw +#define i_opt c_no_cmp +#define i_tag istr +#include <stc/cvec.h> + +void print_elem(csmap_istr_raw p) { + printf("(%d, %s) ", p.first, p.second); +} + +#define using_print_collection(CX) \ + void print_collection_##CX(const CX* t) { \ + printf("%" c_ZU " elements: ", CX##_size(t)); \ + \ + c_foreach (p, CX, *t) { \ + print_elem(CX##_value_toraw(p.ref)); \ + } \ + puts(""); \ + } + +using_print_collection(csmap_istr) +using_print_collection(cvec_istr) + +void findit(csmap_istr c, csmap_istr_key val) +{ + printf("Trying find() on value %d\n", val); + csmap_istr_iter result = csmap_istr_find(&c, val); // prefer contains() or get() + if (result.ref != csmap_istr_end(&c).ref) { + printf("Element found: "); print_elem(csmap_istr_value_toraw(result.ref)); puts(""); + } else { + puts("Element not found."); + } +} + +int main() +{ + c_auto (csmap_istr, m1) + c_auto (cvec_istr, v) + { + c_forlist (i, csmap_istr_raw, {{40, "Zr"}, {45, "Rh"}}) + csmap_istr_emplace(&m1, c_PAIR(i.ref)); + + puts("The starting map m1 is (key, value):"); + print_collection_csmap_istr(&m1); + + typedef cvec_istr_value pair; + cvec_istr_push(&v, (pair){43, "Tc"}); + cvec_istr_push(&v, (pair){41, "Nb"}); + cvec_istr_push(&v, (pair){46, "Pd"}); + cvec_istr_push(&v, (pair){42, "Mo"}); + cvec_istr_push(&v, (pair){44, "Ru"}); + cvec_istr_push(&v, (pair){44, "Ru"}); // attempt a duplicate + + puts("Inserting the following vector data into m1:"); + print_collection_cvec_istr(&v); + + c_foreach (i, cvec_istr, cvec_istr_begin(&v), cvec_istr_end(&v)) + csmap_istr_emplace(&m1, c_PAIR(i.ref)); + + puts("The modified map m1 is (key, value):"); + print_collection_csmap_istr(&m1); + puts(""); + findit(m1, 45); + findit(m1, 6); + } +} diff --git a/misc/examples/csmap_insert.c b/misc/examples/csmap_insert.c new file mode 100644 index 00000000..8f777fc6 --- /dev/null +++ b/misc/examples/csmap_insert.c @@ -0,0 +1,112 @@ +#include <stc/cstr.h> + +// This implements the std::map insert c++ example at: +// https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-19 + +#define i_key int +#define i_val int +#define i_tag ii // Map of int => int +#include <stc/csmap.h> + +#define i_key int +#define i_val_str +#define i_tag istr // Map of int => cstr +#include <stc/csmap.h> + +#define i_val csmap_ii_raw +#define i_opt c_no_cmp +#define i_tag ii +#include <stc/cvec.h> + +void print_ii(csmap_ii map) { + c_foreach (e, csmap_ii, map) + printf("(%d, %d) ", e.ref->first, e.ref->second); + puts(""); +} + +void print_istr(csmap_istr map) { + c_foreach (e, csmap_istr, map) + printf("(%d, %s) ", e.ref->first, cstr_str(&e.ref->second)); + puts(""); +} + +int main() +{ + // insert single values + c_auto (csmap_ii, m1) { + csmap_ii_insert(&m1, 1, 10); + csmap_ii_insert(&m1, 2, 20); + + puts("The original key and mapped values of m1 are:"); + print_ii(m1); + + // intentionally attempt a duplicate, single element + csmap_ii_result ret = csmap_ii_insert(&m1, 1, 111); + if (!ret.inserted) { + csmap_ii_value pr = *ret.ref; + puts("Insert failed, element with key value 1 already exists."); + printf(" The existing element is (%d, %d)\n", pr.first, pr.second); + } + else { + puts("The modified key and mapped values of m1 are:"); + print_ii(m1); + } + puts(""); + + csmap_ii_insert(&m1, 3, 30); + puts("The modified key and mapped values of m1 are:"); + print_ii(m1); + puts(""); + } + + // The templatized version inserting a jumbled range + c_auto (csmap_ii, m2) + c_auto (cvec_ii, v) { + typedef cvec_ii_value ipair; + cvec_ii_push(&v, (ipair){43, 294}); + cvec_ii_push(&v, (ipair){41, 262}); + cvec_ii_push(&v, (ipair){45, 330}); + cvec_ii_push(&v, (ipair){42, 277}); + cvec_ii_push(&v, (ipair){44, 311}); + + puts("Inserting the following vector data into m2:"); + c_foreach (e, cvec_ii, v) + printf("(%d, %d) ", e.ref->first, e.ref->second); + puts(""); + + c_foreach (e, cvec_ii, v) + csmap_ii_insert_or_assign(&m2, e.ref->first, e.ref->second); + + puts("The modified key and mapped values of m2 are:"); + c_foreach (e, csmap_ii, m2) + printf("(%d, %d) ", e.ref->first, e.ref->second); + puts("\n"); + } + + // The templatized versions move-constructing elements + c_auto (csmap_istr, m3) { + csmap_istr_value ip1 = {475, cstr_lit("blue")}, ip2 = {510, cstr_lit("green")}; + + // single element + csmap_istr_insert(&m3, ip1.first, cstr_move(&ip1.second)); + puts("After the first move insertion, m3 contains:"); + print_istr(m3); + + // single element + csmap_istr_insert(&m3, ip2.first, cstr_move(&ip2.second)); + puts("After the second move insertion, m3 contains:"); + print_istr(m3); + puts(""); + } + + c_auto (csmap_ii, m4) { + // Insert the elements from an initializer_list + c_forlist (i, csmap_ii_raw, {{ 4, 44 }, { 2, 22 }, { 3, 33 }, + { 1, 11 }, { 5, 55 }}) + csmap_ii_insert(&m4, c_PAIR(i.ref)); + + puts("After initializer_list insertion, m4 contains:"); + print_ii(m4); + puts(""); + } +} diff --git a/misc/examples/csset_erase.c b/misc/examples/csset_erase.c new file mode 100644 index 00000000..33eb2163 --- /dev/null +++ b/misc/examples/csset_erase.c @@ -0,0 +1,43 @@ +#include <stdio.h> + +#define i_key int +#include <stc/csset.h> + +int main() +{ + c_auto (csset_int, set) + { + c_forlist (i, int, {30, 20, 80, 40, 60, 90, 10, 70, 50}) + csset_int_insert(&set, *i.ref); + + c_foreach (k, csset_int, set) + printf(" %d", *k.ref); + puts(""); + + int val = 64; + csset_int_iter it; + printf("Show values >= %d:\n", val); + it = csset_int_lower_bound(&set, val); + + c_foreach (k, csset_int, it, csset_int_end(&set)) + printf(" %d", *k.ref); + puts(""); + + printf("Erase values >= %d:\n", val); + while (it.ref != csset_int_end(&set).ref) + it = csset_int_erase_at(&set, it); + + c_foreach (k, csset_int, set) + printf(" %d", *k.ref); + puts(""); + + val = 40; + printf("Erase values < %d:\n", val); + it = csset_int_lower_bound(&set, val); + csset_int_erase_range(&set, csset_int_begin(&set), it); + + c_foreach (k, csset_int, set) + printf(" %d", *k.ref); + puts(""); + } +} diff --git a/misc/examples/cstr_match.c b/misc/examples/cstr_match.c new file mode 100644 index 00000000..286ba505 --- /dev/null +++ b/misc/examples/cstr_match.c @@ -0,0 +1,23 @@ +#include <stc/cstr.h> +#include <stc/csview.h> +#include <stdio.h> + +int main() +{ + c_with (cstr ss = cstr_lit("The quick brown fox jumps over the lazy dog.JPG"), cstr_drop(&ss)) { + size_t pos = cstr_find_at(&ss, 0, "brown"); + printf("%" c_ZU " [%s]\n", pos, pos == c_NPOS ? "<NULL>" : cstr_str(&ss) + pos); + printf("equals: %d\n", cstr_equals(&ss, "The quick brown fox jumps over the lazy dog.JPG")); + printf("contains: %d\n", cstr_contains(&ss, "umps ove")); + printf("starts_with: %d\n", cstr_starts_with(&ss, "The quick brown")); + printf("ends_with: %d\n", cstr_ends_with(&ss, ".jpg")); + printf("ends_with: %d\n", cstr_ends_with(&ss, ".JPG")); + + cstr s1 = cstr_lit("hell😀 w😀rl🐨"); + csview ch1 = cstr_u8_chr(&s1, 7); + csview ch2 = cstr_u8_chr(&s1, 10); + printf("%s\nsize: %" c_ZU ", %" c_ZU "\n", cstr_str(&s1), cstr_u8_size(&s1), cstr_size(&s1)); + printf("ch1: %.*s\n", c_ARGSV(ch1)); + printf("ch2: %.*s\n", c_ARGSV(ch2)); + } +} diff --git a/misc/examples/demos.c b/misc/examples/demos.c new file mode 100644 index 00000000..fc3771cb --- /dev/null +++ b/misc/examples/demos.c @@ -0,0 +1,228 @@ +#include <stc/cstr.h> + +void stringdemo1() +{ + printf("\nSTRINGDEMO1\n"); + c_with (cstr cs = cstr_lit("one-nine-three-seven-five"), cstr_drop(&cs)) + { + printf("%s.\n", cstr_str(&cs)); + + cstr_insert(&cs, 3, "-two"); + printf("%s.\n", cstr_str(&cs)); + + cstr_erase(&cs, 7, 5); // -nine + printf("%s.\n", cstr_str(&cs)); + + cstr_replace(&cs, "seven", "four", 1); + printf("%s.\n", cstr_str(&cs)); + + cstr_take(&cs, cstr_from_fmt("%s *** %s", cstr_str(&cs), cstr_str(&cs))); + printf("%s.\n", cstr_str(&cs)); + + printf("find \"four\": %s\n", cstr_str(&cs) + cstr_find(&cs, "four")); + + // reassign: + cstr_assign(&cs, "one two three four five six seven"); + cstr_append(&cs, " eight"); + printf("append: %s\n", cstr_str(&cs)); + } +} + +#define i_val int64_t +#define i_tag ix +#include <stc/cvec.h> + +void vectordemo1() +{ + printf("\nVECTORDEMO1\n"); + c_with (cvec_ix bignums = cvec_ix_with_capacity(100), cvec_ix_drop(&bignums)) + { + cvec_ix_reserve(&bignums, 100); + for (size_t i = 10; i <= 100; i += 10) + cvec_ix_push(&bignums, i * i); + + printf("erase - %d: %" PRIu64 "\n", 3, bignums.data[3]); + cvec_ix_erase_n(&bignums, 3, 1); // erase index 3 + + cvec_ix_pop(&bignums); // erase the last + cvec_ix_erase_n(&bignums, 0, 1); // erase the first + + for (size_t i = 0; i < cvec_ix_size(&bignums); ++i) { + printf("%" c_ZU ": %" PRIu64 "\n", i, bignums.data[i]); + } + } +} + +#define i_val_str +#include <stc/cvec.h> + +void vectordemo2() +{ + printf("\nVECTORDEMO2\n"); + c_auto (cvec_str, names) { + cvec_str_emplace_back(&names, "Mary"); + cvec_str_emplace_back(&names, "Joe"); + cvec_str_emplace_back(&names, "Chris"); + cstr_assign(&names.data[1], "Jane"); // replace Joe + printf("names[1]: %s\n", cstr_str(&names.data[1])); + + cvec_str_sort(&names); // Sort the array + c_foreach (i, cvec_str, names) + printf("sorted: %s\n", cstr_str(i.ref)); + } +} + +#define i_val int +#define i_tag ix +#define i_extern // define _clist_mergesort() once +#include <stc/clist.h> + +void listdemo1() +{ + printf("\nLISTDEMO1\n"); + c_auto (clist_ix, nums, nums2) + { + for (int i = 0; i < 10; ++i) + clist_ix_push_back(&nums, i); + for (int i = 100; i < 110; ++i) + clist_ix_push_back(&nums2, i); + + /* splice nums2 to front of nums */ + clist_ix_splice(&nums, clist_ix_begin(&nums), &nums2); + c_foreach (i, clist_ix, nums) + printf("spliced: %d\n", *i.ref); + puts(""); + + *clist_ix_find(&nums, 104).ref += 50; + clist_ix_remove(&nums, 103); + clist_ix_iter it = clist_ix_begin(&nums); + clist_ix_erase_range(&nums, clist_ix_advance(it, 5), clist_ix_advance(it, 15)); + clist_ix_pop_front(&nums); + clist_ix_push_back(&nums, -99); + clist_ix_sort(&nums); + + c_foreach (i, clist_ix, nums) + printf("sorted: %d\n", *i.ref); + } +} + +#define i_key int +#define i_tag i +#include <stc/cset.h> + +void setdemo1() +{ + printf("\nSETDEMO1\n"); + cset_i nums = cset_i_init(); + cset_i_insert(&nums, 8); + cset_i_insert(&nums, 11); + + c_foreach (i, cset_i, nums) + printf("set: %d\n", *i.ref); + cset_i_drop(&nums); +} + +#define i_key int +#define i_val int +#define i_tag ii +#include <stc/cmap.h> + +void mapdemo1() +{ + printf("\nMAPDEMO1\n"); + cmap_ii nums = cmap_ii_init(); + cmap_ii_insert(&nums, 8, 64); + cmap_ii_insert(&nums, 11, 121); + printf("val 8: %d\n", *cmap_ii_at(&nums, 8)); + cmap_ii_drop(&nums); +} + +#define i_key_str +#define i_val int +#define i_tag si +#include <stc/cmap.h> + +void mapdemo2() +{ + printf("\nMAPDEMO2\n"); + c_auto (cmap_si, nums) + { + cmap_si_emplace_or_assign(&nums, "Hello", 64); + cmap_si_emplace_or_assign(&nums, "Groovy", 121); + cmap_si_emplace_or_assign(&nums, "Groovy", 200); // overwrite previous + + // iterate the map: + for (cmap_si_iter i = cmap_si_begin(&nums); i.ref != cmap_si_end(&nums).ref; cmap_si_next(&i)) + printf("long: %s: %d\n", cstr_str(&i.ref->first), i.ref->second); + + // or rather use the short form: + c_foreach (i, cmap_si, nums) + printf("short: %s: %d\n", cstr_str(&i.ref->first), i.ref->second); + } +} + +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +void mapdemo3() +{ + printf("\nMAPDEMO3\n"); + cmap_str table = cmap_str_init(); + cmap_str_emplace(&table, "Map", "test"); + cmap_str_emplace(&table, "Make", "my"); + cmap_str_emplace(&table, "Sunny", "day"); + cmap_str_iter it = cmap_str_find(&table, "Make"); + c_foreach (i, cmap_str, table) + printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + printf("size %" c_ZU ": remove: Make: %s\n", cmap_str_size(&table), cstr_str(&it.ref->second)); + //cmap_str_erase(&table, "Make"); + cmap_str_erase_at(&table, it); + + printf("size %" c_ZU "\n", cmap_str_size(&table)); + c_foreach (i, cmap_str, table) + printf("entry: %s: %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); + cmap_str_drop(&table); // frees key and value cstrs, and hash table. +} + +#define i_val float +#define i_tag f +#include <stc/carr3.h> + +void arraydemo1() +{ + printf("\nARRAYDEMO1\n"); + c_with (carr3_f arr3 = carr3_f_with_size(30, 20, 10, 0.0f), + carr3_f_drop(&arr3)) + { + arr3.data[5][4][3] = 10.2f; + float **arr2 = arr3.data[5]; + float *arr1 = arr3.data[5][4]; + + printf("arr3: %" c_ZU ": (%" c_ZU ", %" c_ZU ", %" c_ZU ") = %" c_ZU "\n", sizeof(arr3), + arr3.xdim, arr3.ydim, arr3.zdim, carr3_f_size(&arr3)); + + printf("%g\n", arr1[3]); // = 10.2 + printf("%g\n", arr2[4][3]); // = 10.2 + printf("%g\n", arr3.data[5][4][3]); // = 10.2 + + float x = 0.0; + c_foreach (i, carr3_f, arr3) + *i.ref = ++x; + printf("%g\n", arr3.data[29][19][9]); // = 6000 + } +} + + +int main() +{ + stringdemo1(); + vectordemo1(); + vectordemo2(); + listdemo1(); + setdemo1(); + mapdemo1(); + mapdemo2(); + mapdemo3(); + arraydemo1(); +} diff --git a/misc/examples/forfilter.c b/misc/examples/forfilter.c new file mode 100644 index 00000000..ba4dce7f --- /dev/null +++ b/misc/examples/forfilter.c @@ -0,0 +1,144 @@ +#include <stdio.h> +#define i_extern +#include <stc/cstr.h> +#include <stc/csview.h> +#include <stc/views.h> + +#define i_type IVec +#define i_val int +#include <stc/cstack.h> + +#define i_type SVec +#define i_valclass csview +#include <stc/cstack.h> + +// filters and transforms: +#define flt_skipValue(i, x) (*i.ref != (x)) +#define flt_isEven(i) ((*i.ref & 1) == 0) +#define flt_isOdd(i) (*i.ref & 1) +#define flt_square(i) (*i.ref * *i.ref) + +void demo1(void) +{ + c_auto (IVec, vec) { + c_forlist (i, int, {0, 1, 2, 3, 4, 5, 80, 6, 7, 80, 8, 9, 80, 10, 11, 12, 13, 14, 15, 80, 16, 17}) + IVec_push(&vec, *i.ref); + + puts("demo1:"); + c_forfilter (i, IVec, vec, flt_skipValue(i, 80)) + printf(" %d", *i.ref); + puts(""); + + int res, sum = 0; + c_forfilter (i, IVec, vec + , c_flt_skipwhile(i, *i.ref != 80) + && c_flt_skip(i, 1) + && c_flt_skipwhile(i, *i.ref != 80) + && flt_isEven(i) + && flt_skipValue(i, 80) + , c_flt_take(i, 5) // short-circuit + ){ + sum += res = flt_square(i); + printf(" %d", res); + } + printf("\n sum: %d\n", sum); + } +} + + +/* Rust: +fn main() { + let vector = (1..) // Infinite range of integers + .skip_while(|x| *x != 11) // Skip initial numbers unequal 11 + .filter(|x| x % 2 != 0) // Collect odd numbers + .take(5) // Only take five numbers + .map(|x| x * x) // Square each number + .collect::<Vec<usize>>(); // Return as a new Vec<usize> + println!("{:?}", vector); // Print result +} +*/ + +void demo2(void) +{ + c_auto (IVec, vector) { + puts("demo2:"); + + c_forfilter (x, crange, crange_literal(INT64_MAX) + , c_flt_skipwhile(x, *x.ref != 11) + && *x.ref % 2 != 0 + , c_flt_take(x, 5)) + IVec_push(&vector, *x.ref * *x.ref); + c_foreach (x, IVec, vector) printf(" %d", *x.ref); + puts(""); + } +} + +/* Rust: +fn main() { + let sentence = "This is a sentence in Rust."; + let words: Vec<&str> = sentence + .split_whitespace() + .collect(); + let words_containing_i: Vec<&str> = words + .into_iter() + .filter(|word| word.contains("i")) + .collect(); + println!("{:?}", words_containing_i); +} +*/ +void demo3(void) +{ + c_auto (SVec, words, words_containing_i) { + const char* sentence = "This is a sentence in C99."; + c_fortoken (w, sentence, " ") + SVec_push(&words, *w.ref); + + c_forfilter (w, SVec, words, + csview_contains(*w.ref, "i")) + SVec_push(&words_containing_i, *w.ref); + + puts("demo3:"); + c_foreach (w, SVec, words_containing_i) + printf(" %.*s", c_ARGSV(*w.ref)); + puts(""); + } +} + +void demo4(void) +{ + csview s = c_SV("ab123cReAghNGnΩoEp"); // Ω = multi-byte + c_auto (cstr, out) { + c_forfilter (i, csview, s, utf8_isupper(utf8_peek(i.ref))) { + char chr[4]; + utf8_encode(chr, utf8_tolower(utf8_peek(i.ref))); + cstr_push(&out, chr); + } + puts("demo4:"); + printf(" %s\n", cstr_str(&out)); + } +} + +void demo5(void) +{ + #define flt_even(i) ((*i.ref & 1) == 0) + #define flt_mid_decade(i) ((*i.ref % 10) != 0) + puts("demo5:"); + crange r1 = crange_make(1963, INT32_MAX); + c_forfilter (i, crange, r1 + , c_flt_skip(i,15) + && c_flt_skipwhile(i, flt_mid_decade(i)) + && c_flt_skip(i,30) + && flt_even(i) + , c_flt_take(i,10)) + printf(" %lld", *i.ref); + puts(""); +} + +int main(void) +{ + demo1(); + demo2(); + demo3(); + demo4(); + demo5(); +} diff --git a/misc/examples/forloops.c b/misc/examples/forloops.c new file mode 100644 index 00000000..2654f095 --- /dev/null +++ b/misc/examples/forloops.c @@ -0,0 +1,81 @@ +#include <stdio.h>
+#include <stc/views.h>
+
+#define i_type IVec
+#define i_val int
+#include <stc/cstack.h>
+
+#define i_type IMap
+#define i_key int
+#define i_val int
+#include <stc/cmap.h>
+
+
+int main()
+{
+ puts("c_forrange:");
+ c_forrange (30) printf(" xx");
+ puts("");
+
+ c_forrange (i, 30) printf(" %lld", i);
+ puts("");
+
+ c_forrange (i, 30, 60) printf(" %lld", i);
+ puts("");
+
+ c_forrange (i, 30, 90, 2) printf(" %lld", i);
+
+
+ puts("\n\nc_forlist:");
+ c_forlist (i, int, {12, 23, 453, 65, 676})
+ printf(" %d", *i.ref);
+ puts("");
+
+ c_forlist (i, const char*, {"12", "23", "453", "65", "676"})
+ printf(" %s", *i.ref);
+ puts("");
+
+ c_forlist (i, const char*, {"12", "23", "453", "65", "676"})
+ printf(" %s", i.data[i.size - 1 - i.index]);
+
+
+ c_auto (IVec, vec)
+ c_auto (IMap, map)
+ {
+ c_forlist (i, int, {12, 23, 453, 65, 113, 215, 676, 34, 67, 20, 27, 66, 189, 45, 280, 199})
+ IVec_push(&vec, *i.ref);
+
+ c_forlist (i, IMap_value, {{12, 23}, {453, 65}, {676, 123}, {34, 67}})
+ IMap_push(&map, *i.ref);
+
+ puts("\n\nc_foreach:");
+ c_foreach (i, IVec, vec)
+ printf(" %d", *i.ref);
+ puts("");
+
+ c_foreach (i, IMap, map)
+ printf(" (%d %d)", i.ref->first, i.ref->second);
+
+ puts("\n\nc_forpair:");
+ c_forpair (key, val, IMap, map)
+ printf(" (%d %d)", *_.key, *_.val);
+
+ puts("\n\nc_forwhile:");
+ c_forwhile (i, IVec, IVec_begin(&vec), i.index < 3)
+ printf(" %d", *i.ref);
+
+ #define isOdd(i) (*i.ref & 1)
+
+ puts("\n\nc_forfilter:");
+ c_forfilter (i, IVec, vec
+ , c_flt_skipwhile(i, *i.ref != 65)
+ && c_flt_takewhile(i, *i.ref != 280)
+ && c_flt_skipwhile(i, isOdd(i))
+ && isOdd(i)
+ && c_flt_skip(i, 2)
+ , c_flt_take(i, 1))
+ printf(" %d", *i.ref);
+ puts("");
+ // 189
+ }
+}
diff --git a/misc/examples/gauss1.c b/misc/examples/gauss1.c new file mode 100644 index 00000000..675ff338 --- /dev/null +++ b/misc/examples/gauss1.c @@ -0,0 +1,56 @@ +#include <time.h> +#include <math.h> + +#include <stc/crandom.h> +#include <stc/cstr.h> + +// Declare int -> int hashmap. Uses typetag 'ii' for ints. +#define i_key int +#define i_val int +#define i_tag ii +#include <stc/cmap.h> + +// Declare int vector with entries from the cmap. +#define i_val cmap_ii_value +#define i_less(x, y) x->first < y->first +#define i_tag ii +#include <stc/cvec.h> + +int main() +{ + enum {N = 10000000}; + const double Mean = -12.0, StdDev = 6.0, Scale = 74; + + printf("Demo of gaussian / normal distribution of %d random samples\n", N); + + // Setup random engine with normal distribution. + uint64_t seed = time(NULL); + stc64_t rng = stc64_new(seed); + stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev); + + // Create and init histogram vec and map with defered destructors: + c_auto (cvec_ii, histvec) + c_auto (cmap_ii, histmap) + { + c_forrange (N) { + int index = (int) round( stc64_normalf(&rng, &dist) ); + cmap_ii_insert(&histmap, index, 0).ref->second += 1; + } + + // Transfer map to vec and sort it by map keys. + c_foreach (i, cmap_ii, histmap) + cvec_ii_push(&histvec, (cmap_ii_value){i.ref->first, i.ref->second}); + + cvec_ii_sort(&histvec); + + // Print the gaussian bar chart + c_auto (cstr, bar) + c_foreach (i, cvec_ii, histvec) { + size_t n = (size_t) (i.ref->second * StdDev * Scale * 2.5 / (float)N); + if (n > 0) { + cstr_resize(&bar, n, '*'); + printf("%4d %s\n", i.ref->first, cstr_str(&bar)); + } + } + } +} diff --git a/misc/examples/gauss2.c b/misc/examples/gauss2.c new file mode 100644 index 00000000..2e07c5a5 --- /dev/null +++ b/misc/examples/gauss2.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <time.h> + +#define STC_IMPLEMENT +#include <stc/crandom.h> +#include <stc/cstr.h> + +// Declare int -> int sorted map. +#define i_key int +#define i_val size_t +#include <stc/csmap.h> + +int main() +{ + enum {N = 10000000}; + const double Mean = -12.0, StdDev = 6.0, Scale = 74; + + printf("Demo of gaussian / normal distribution of %d random samples\n", N); + + // Setup random engine with normal distribution. + uint64_t seed = time(NULL); + stc64_t rng = stc64_new(seed); + stc64_normalf_t dist = stc64_normalf_new(Mean, StdDev); + + // Create and init histogram map with defered destruct + c_auto (csmap_int, mhist) + { + c_forrange (N) { + int index = (int) round( stc64_normalf(&rng, &dist) ); + csmap_int_insert(&mhist, index, 0).ref->second += 1; + } + + // Print the gaussian bar chart + c_auto (cstr, bar) + c_forpair (index, count, csmap_int, mhist) { + size_t n = (size_t) (*_.count * StdDev * Scale * 2.5 / (float)N); + if (n > 0) { + cstr_resize(&bar, n, '*'); + printf("%4d %s\n", *_.index, cstr_str(&bar)); + } + } + } +} diff --git a/misc/examples/hashmap.c b/misc/examples/hashmap.c new file mode 100644 index 00000000..f59ed824 --- /dev/null +++ b/misc/examples/hashmap.c @@ -0,0 +1,48 @@ +// https://doc.rust-lang.org/rust-by-example/std/hash.html +#include <stc/cstr.h> +#define i_key_str +#define i_val_str +#include <stdio.h> +#include <stc/cmap.h> + +const char* call(const char* number) { + if (!strcmp(number, "798-1364")) + return "We're sorry, the call cannot be completed as dialed." + " Please hang up and try again."; + else if (!strcmp(number, "645-7689")) + return "Hello, this is Mr. Awesome's Pizza. My name is Fred." + " What can I get for you today?"; + else + return "Hi! Who is this again?"; +} + +int main(void) { + c_auto (cmap_str, contacts) + { + cmap_str_emplace(&contacts, "Daniel", "798-1364"); + cmap_str_emplace(&contacts, "Ashley", "645-7689"); + cmap_str_emplace(&contacts, "Katie", "435-8291"); + cmap_str_emplace(&contacts, "Robert", "956-1745"); + + const cmap_str_value* v; + if ((v = cmap_str_get(&contacts, "Daniel"))) + printf("Calling Daniel: %s\n", call(cstr_str(&v->second))); + else + printf("Don't have Daniel's number."); + + cmap_str_emplace_or_assign(&contacts, "Daniel", "164-6743"); + + if ((v = cmap_str_get(&contacts, "Ashley"))) + printf("Calling Ashley: %s\n", call(cstr_str(&v->second))); + else + printf("Don't have Ashley's number."); + + cmap_str_erase(&contacts, "Ashley"); + + puts(""); + c_forpair (contact, number, cmap_str, contacts) { + printf("Calling %s: %s\n", cstr_str(_.contact), call(cstr_str(_.number))); + } + puts(""); + } +} diff --git a/misc/examples/inits.c b/misc/examples/inits.c new file mode 100644 index 00000000..021a3e0a --- /dev/null +++ b/misc/examples/inits.c @@ -0,0 +1,116 @@ +#include <stc/cstr.h> + +#define i_key int +#define i_val_str +#define i_tag id // Map of int => cstr +#include <stc/cmap.h> + +#define i_key_str +#define i_val int +#define i_tag cnt // Map of cstr => int +#include <stc/cmap.h> + +typedef struct {int x, y;} ipair_t; +inline static int ipair_cmp(const ipair_t* a, const ipair_t* b) { + int c = c_default_cmp(&a->x, &b->x); + return c ? c : c_default_cmp(&a->y, &b->y); +} + + +#define i_val ipair_t +#define i_cmp ipair_cmp +#define i_tag ip +#include <stc/cvec.h> + +#define i_val ipair_t +#define i_cmp ipair_cmp +#define i_tag ip +#define i_extern // define _clist_mergesort() once +#include <stc/clist.h> + +#define i_val float +#define i_tag f +#include <stc/cpque.h> + +int main(void) +{ + // CVEC FLOAT / PRIORITY QUEUE + + c_auto (cpque_f, floats) { + const float nums[] = {4.0f, 2.0f, 5.0f, 3.0f, 1.0f}; + + // PRIORITY QUEUE + c_forrange (i, c_arraylen(nums)) + cpque_f_push(&floats, nums[i]); + + puts("\npop and show high priorites first:"); + while (! cpque_f_empty(&floats)) { + printf("%.1f ", *cpque_f_top(&floats)); + cpque_f_pop(&floats); + } + puts("\n"); + } + + // CMAP ID + + int year = 2020; + c_auto (cmap_id, idnames) { + cmap_id_emplace(&idnames, 100, "Hello"); + cmap_id_insert(&idnames, 110, cstr_lit("World")); + cmap_id_insert(&idnames, 120, cstr_from_fmt("Howdy, -%d-", year)); + + c_foreach (i, cmap_id, idnames) + printf("%d: %s\n", i.ref->first, cstr_str(&i.ref->second)); + puts(""); + } + + // CMAP CNT + + c_auto (cmap_cnt, countries) { + c_forlist (i, cmap_cnt_raw, { + {"Norway", 100}, + {"Denmark", 50}, + {"Iceland", 10}, + {"Belgium", 10}, + {"Italy", 10}, + {"Germany", 10}, + {"Spain", 10}, + {"France", 10}, + }) cmap_cnt_emplace(&countries, c_PAIR(i.ref)); + + cmap_cnt_emplace(&countries, "Greenland", 0).ref->second += 20; + cmap_cnt_emplace(&countries, "Sweden", 0).ref->second += 20; + cmap_cnt_emplace(&countries, "Norway", 0).ref->second += 20; + cmap_cnt_emplace(&countries, "Finland", 0).ref->second += 20; + + c_forpair (country, health, cmap_cnt, countries) + printf("%s: %d\n", cstr_str(_.country), *_.health); + puts(""); + } + + // CVEC PAIR + + c_auto (cvec_ip, pairs1) { + c_forlist (i, ipair_t, {{5, 6}, {3, 4}, {1, 2}, {7, 8}}) + cvec_ip_push_back(&pairs1, *i.ref); + + cvec_ip_sort(&pairs1); + + c_foreach (i, cvec_ip, pairs1) + printf("(%d %d) ", i.ref->x, i.ref->y); + puts(""); + } + + // CLIST PAIR + + c_auto (clist_ip, pairs2) { + c_forlist (i, ipair_t, {{5, 6}, {3, 4}, {1, 2}, {7, 8}}) + clist_ip_push_back(&pairs2, *i.ref); + + clist_ip_sort(&pairs2); + + c_foreach (i, clist_ip, pairs2) + printf("(%d %d) ", i.ref->x, i.ref->y); + puts(""); + } +} diff --git a/misc/examples/intrusive.c b/misc/examples/intrusive.c new file mode 100644 index 00000000..acf4416d --- /dev/null +++ b/misc/examples/intrusive.c @@ -0,0 +1,52 @@ +// Example of intrusive list by using the node API and typesafe c_container_of(). + +#include <stdio.h> + +#define i_type List1 +#define i_val int +#define i_extern // implement List1_sort() +#include <stc/clist.h> + +#define i_type List2 +#define i_val List1_node +#define i_opt c_no_cmp // no elem. comparison +#include <stc/clist.h> + +int main() +{ + c_auto (List2, list2) + { + List1 list1 = List1_init(); // should not be destroyed, list2 will destroy shared nodes. + + c_forlist (i, int, {6, 9, 3, 1, 7, 4, 5, 2, 8}) + List2_push_back(&list2, (List1_node){NULL, *i.ref}); + + c_foreach (i, List2, list2) + List1_push_node_back(&list1, c_container_of(&i.ref->value, List1_node, value)); + + printf("list1:"); + c_foreach (i, List1, list1) printf(" %d", *i.ref); + printf("\nlist2:"); + c_foreach (i, List2, list2) printf(" %d", i.ref->value); + + printf("\nsort list1"); + List1_sort(&list1); + + printf("\nlist1:"); + c_foreach (i, List1, list1) printf(" %d", *i.ref); + printf("\nlist2:"); + c_foreach (i, List2, list2) printf(" %d", i.ref->value); + + 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))); + } + printf("\nlist1:"); + c_foreach (i, List1, list1) printf(" %d", *i.ref); + printf("\nlist2:"); + c_foreach (i, List2, list2) printf(" %d", i.ref->value); + puts(""); + } +} diff --git a/misc/examples/list.c b/misc/examples/list.c new file mode 100644 index 00000000..a538d93c --- /dev/null +++ b/misc/examples/list.c @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <time.h> + +#define STC_IMPLEMENT +#define STC_EXTERN + +#define i_val double +#define i_tag fx +#include <stc/clist.h> +#include <stc/crandom.h> + +int main() { + const int n = 2000000; + + c_auto (clist_fx, list) + { + stc64_t rng = stc64_new(1234); + stc64_uniformf_t dist = stc64_uniformf_new(100.0f, n); + int m = 0; + c_forrange (n) + clist_fx_push_back(&list, stc64_uniformf(&rng, &dist)), ++m; + double sum = 0.0; + printf("sumarize %d:\n", m); + c_foreach (i, clist_fx, list) + sum += *i.ref; + printf("sum %f\n\n", sum); + + c_forwhile (i, clist_fx, clist_fx_begin(&list), i.index < 10) + printf("%8d: %10f\n", (int)i.index, *i.ref); + + puts("sort"); + clist_fx_sort(&list); // mergesort O(n*log n) + puts("sorted"); + + c_forwhile (i, clist_fx, clist_fx_begin(&list), i.index < 10) + printf("%8d: %10f\n", (int)i.index, *i.ref); + puts(""); + + clist_fx_clear(&list); + c_forlist (i, int, {10, 20, 30, 40, 30, 50}) + clist_fx_push_back(&list, *i.ref); + + const double* v = clist_fx_get(&list, 30); + printf("found: %f\n", *v); + c_foreach (i, clist_fx, list) printf(" %g", *i.ref); + puts(""); + + clist_fx_remove(&list, 30); + clist_fx_insert_at(&list, clist_fx_begin(&list), 5); // same as push_front() + clist_fx_push_back(&list, 500); + clist_fx_push_front(&list, 1964); + clist_fx_iter it = clist_fx_begin(&list); + printf("Full: "); + c_foreach (i, clist_fx, list) + printf(" %g", *i.ref); + printf("\nSubs: "); + c_foreach (i, clist_fx, clist_fx_advance(it, 4), clist_fx_end(&list)) + printf(" %g", *i.ref); + puts(""); + } +} diff --git a/misc/examples/list_erase.c b/misc/examples/list_erase.c new file mode 100644 index 00000000..c1a2aa97 --- /dev/null +++ b/misc/examples/list_erase.c @@ -0,0 +1,32 @@ +// erasing from clist +#include <stdio.h> + +#define i_type IList +#define i_val int +#include <stc/clist.h> + +int main () +{ + c_with (IList L = IList_init(), IList_drop(&L)) + { + c_forlist (i, int, {10, 20, 30, 40, 50}) + IList_push(&L, *i.ref); + + c_foreach (x, IList, L) + printf("%d ", *x.ref); + puts(""); + // 10 20 30 40 50 + IList_iter it = IList_begin(&L); // ^ + IList_next(&it); + it = IList_erase_at(&L, it); // 10 30 40 50 + // ^ + IList_iter end = IList_end(&L); // + IList_next(&it); + it = IList_erase_range(&L, it, end); // 10 30 + // ^ + printf("list contains:"); + c_foreach (x, IList, L) + printf(" %d", *x.ref); + puts(""); + } +} diff --git a/misc/examples/list_splice.c b/misc/examples/list_splice.c new file mode 100644 index 00000000..f7bac0d6 --- /dev/null +++ b/misc/examples/list_splice.c @@ -0,0 +1,43 @@ +#include <stdio.h> + +#define i_val int +#define i_tag i +#define i_extern // define _clist_mergesort() once +#include <stc/clist.h> + +void print_ilist(const char* s, clist_i list) +{ + printf("%s", s); + c_foreach (i, clist_i, list) { + printf(" %d", *i.ref); + } + puts(""); +} + +int main () +{ + c_auto (clist_i, list1, list2) + { + c_forlist (i, int, {1, 2, 3, 4, 5}) + clist_i_push_back(&list1, *i.ref); + + c_forlist (i, int, {10, 20, 30, 40, 50}) + clist_i_push_back(&list2, *i.ref); + + print_ilist("list1:", list1); + print_ilist("list2:", list2); + + clist_i_iter it = clist_i_advance(clist_i_begin(&list1), 2); + it = clist_i_splice(&list1, it, &list2); + + puts("After splice"); + print_ilist("list1:", list1); + print_ilist("list2:", list2); + + clist_i_splice_range(&list2, clist_i_begin(&list2), &list1, it, clist_i_end(&list1)); + + puts("After splice_range"); + print_ilist("list1:", list1); + print_ilist("list2:", list2); + } +} diff --git a/misc/examples/lower_bound.c b/misc/examples/lower_bound.c new file mode 100644 index 00000000..2477bc14 --- /dev/null +++ b/misc/examples/lower_bound.c @@ -0,0 +1,62 @@ +#include <stdio.h> + +#define i_val int +#include <stc/cvec.h> + +#define i_val int +#include <stc/csset.h> + +int main() +{ + // TEST SORTED VECTOR + c_auto (cvec_int, vec) + { + int key, *res; + + c_forlist (i, int, {40, 600, 1, 7000, 2, 500, 30}) + cvec_int_push(&vec, *i.ref); + + cvec_int_sort(&vec); + + key = 500; + res = cvec_int_lower_bound(&vec, key).ref; + if (res != cvec_int_end(&vec).ref) + printf("Sorted Vec %d: lower bound: %d\n", key, *res); // 600 + + key = 550; + res = cvec_int_lower_bound(&vec, key).ref; + if (res != cvec_int_end(&vec).ref) + printf("Sorted Vec %d: lower_bound: %d\n", key, *res); // 500 + + key = 500; + res = cvec_int_binary_search(&vec, key).ref; + if (res != cvec_int_end(&vec).ref) + printf("Sorted Vec %d: bin. search: %d\n", key, *res); // 500 + puts(""); + } + + // TEST SORTED SET + c_auto (csset_int, set) + { + int key, *res; + + c_forlist (i, int, {40, 600, 1, 7000, 2, 500, 30}) + csset_int_push(&set, *i.ref); + + key = 500; + res = csset_int_lower_bound(&set, key).ref; + if (res != csset_int_end(&set).ref) + printf("Sorted Set %d: lower bound: %d\n", key, *res); // 600 + + key = 550; + res = csset_int_lower_bound(&set, key).ref; + if (res != csset_int_end(&set).ref) + printf("Sorted Set %d: lower bound: %d\n", key, *res); // 600 + + key = 500; + res = csset_int_find(&set, key).ref; + if (res != csset_int_end(&set).ref) + printf("Sorted Set %d: find : %d\n", key, *res); // 600 + } + return 0; +} diff --git a/misc/examples/make.sh b/misc/examples/make.sh new file mode 100755 index 00000000..bd1392fc --- /dev/null +++ b/misc/examples/make.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +if [ "$(uname)" = 'Linux' ]; then + sanitize='-fsanitize=address' + clibs='-lm' # -pthread + oflag='-o ' +fi + +#cc=gcc; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall $sanitize" +cc=gcc; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wsign-compare -Wwrite-strings" # -Wconversion +#cc=tcc; cflags="-Wall -std=c99" +#cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -Wsign-compare -Wwrite-strings" +#cc=clang; cflags="-s -O2 -std=c99 -Werror -Wfatal-errors -Wpedantic -Wall -DSTC_CSTR_V1 -DSTC_CSMAP_V1" +#cc=gcc; cflags="-x c++ -s -O2 -Wall -std=c++20" +#cc=g++; cflags="-x c++ -s -O2 -Wall" +#cc=cl; cflags="-O2 -nologo -W2 -MD" +#cc=cl; cflags="-nologo -TP" +#cc=cl; cflags="-nologo -std:c11" + +if [ "$cc" = "cl" ]; then + oflag='/Fe:' +else + oflag='-o ' +fi + +run=0 +if [ "$1" = '-h' -o "$1" = '--help' ]; then + echo usage: runall.sh [-run] [compiler + options] + exit +fi +if [ "$1" = '-run' ]; then + run=1 + shift +fi +if [ ! -z "$1" ] ; then + comp="$@" +else + comp="$cc $cflags" +fi + +if [ $run = 0 ] ; then + for i in *.c ; do + echo $comp -I../include $i $clibs $oflag$(basename $i .c).exe + $comp -I../include $i $clibs $oflag$(basename $i .c).exe + done +else + for i in *.c ; do + echo $comp -I../include $i $clibs + $comp -I../include $i $clibs + if [ -f $(basename -s .c $i).exe ]; then ./$(basename -s .c $i).exe; fi + if [ -f ./a.exe ]; then ./a.exe; fi + if [ -f ./a.out ]; then ./a.out; fi + done +fi + +rm -f a.out *.o *.obj # *.exe diff --git a/misc/examples/mapmap.c b/misc/examples/mapmap.c new file mode 100644 index 00000000..488cc539 --- /dev/null +++ b/misc/examples/mapmap.c @@ -0,0 +1,68 @@ +// create a structure like: std::map<std::string, std::map<std::string, std::string>>: + +#include <stc/cstr.h> + +// People: std::map<std::string, std::string> +#define i_type People +#define i_key_str +#define i_val_str +#define i_keydrop(p) (printf("kdrop: %s\n", cstr_str(p)), cstr_drop(p)) // override +#include <stc/csmap.h> + +// Departments: std::map<std::string, People> +#define i_type Departments +#define i_key_str +#define i_valclass People +// Shorthand for: +// #define i_val People +// #define i_cmp People_cmp +// #define i_valclone People_clone +// #define i_valdrop People_drop +#include <stc/csmap.h> + + +void add(Departments* deps, const char* name, const char* email, const char* dep) +{ + People *people = &Departments_insert(deps, cstr_from(dep), People_init()).ref->second; + People_emplace_or_assign(people, name, email); +} + +int contains(Departments* map, const char* name) +{ + int count = 0; + c_foreach (i, Departments, *map) + if (People_contains(&i.ref->second, name)) + ++count; + return count; +} + +int main(void) +{ + c_auto (Departments, map) + { + add(&map, "Anna Kendro", "[email protected]", "Support"); + add(&map, "Terry Dane", "[email protected]", "Development"); + add(&map, "Kik Winston", "[email protected]", "Finance"); + add(&map, "Nancy Drew", "[email protected]", "Development"); + add(&map, "Nick Denton", "[email protected]", "Finance"); + add(&map, "Stan Whiteword", "[email protected]", "Marketing"); + add(&map, "Serena Bath", "[email protected]", "Support"); + add(&map, "Patrick Dust", "[email protected]", "Finance"); + add(&map, "Red Winger", "[email protected]", "Marketing"); + add(&map, "Nick Denton", "[email protected]", "Support"); + add(&map, "Colin Turth", "[email protected]", "Support"); + add(&map, "Dennis Kay", "[email protected]", "Marketing"); + add(&map, "Anne Dickens", "[email protected]", "Development"); + + c_foreach (i, Departments, map) + c_forpair (name, email, People, i.ref->second) + printf("%s: %s - %s\n", cstr_str(&i.ref->first), cstr_str(_.name), cstr_str(_.email)); + puts(""); + + printf("found Nick Denton: %d\n", contains(&map, "Nick Denton")); + printf("found Patrick Dust: %d\n", contains(&map, "Patrick Dust")); + printf("found Dennis Kay: %d\n", contains(&map, "Dennis Kay")); + printf("found Serena Bath: %d\n", contains(&map, "Serena Bath")); + puts("Done"); + } +} diff --git a/misc/examples/mmap.c b/misc/examples/mmap.c new file mode 100644 index 00000000..3934cf26 --- /dev/null +++ b/misc/examples/mmap.c @@ -0,0 +1,72 @@ +// This implements the multimap c++ example found at: +// https://en.cppreference.com/w/cpp/container/multimap/insert + +// Multimap entries +#include <stc/cstr.h> +#define i_val_str +//#define i_valdrop(x) (printf("drop %s\n", cstr_str(x)), cstr_drop(x)) +#define i_extern // define _clist_mergesort() once +#include <stc/clist.h> + +// Map of int => clist_str. +#define i_type Multimap +#define i_key int +#define i_valclass clist_str // uses clist_str as i_val and binds clist_str_clone, clist_str_drop +#define i_cmp -c_default_cmp // like std::greater<int> +#include <stc/csmap.h> + +void print(const char* lbl, const Multimap mmap) +{ + printf("%s ", lbl); + c_foreach (e, Multimap, mmap) { + c_foreach (s, clist_str, e.ref->second) + printf("{%d,%s} ", e.ref->first, cstr_str(s.ref)); + } + puts(""); +} + +void insert(Multimap* mmap, int key, const char* str) +{ + clist_str *list = &Multimap_insert(mmap, key, clist_str_init()).ref->second; + clist_str_emplace_back(list, str); +} + +int main() +{ + c_auto (Multimap, mmap) + { + typedef struct {int a; const char* b;} pair; + + // list-initialize + c_forlist (i, pair, {{2, "foo"}, {2, "bar"}, {3, "baz"}, {1, "abc"}, {5, "def"}}) + insert(&mmap, i.ref->a, i.ref->b); + print("#1", mmap); + + // insert using value_type + insert(&mmap, 5, "pqr"); + print("#2", mmap); + + // insert using make_pair + insert(&mmap, 6, "uvw"); + print("#3", mmap); + + insert(&mmap, 7, "xyz"); + print("#4", mmap); + + // insert using initialization_list + c_forlist (i, pair, {{5, "one"}, {5, "two"}}) + insert(&mmap, i.ref->a, i.ref->b); + print("#5", mmap); + + // FOLLOWING NOT IN ORIGINAL EXAMPLE: + // erase all entries with key 5 + Multimap_erase(&mmap, 5); + print("+5", mmap); + + + Multimap_clear(&mmap); + c_forlist (i, pair, {{1, "ä"}, {2, "ё"}, {2, "ö"}, {3, "ü"}}) + insert(&mmap, i.ref->a, i.ref->b); + print("#6", mmap); + } +} diff --git a/misc/examples/multimap.c b/misc/examples/multimap.c new file mode 100644 index 00000000..e72bdce3 --- /dev/null +++ b/misc/examples/multimap.c @@ -0,0 +1,99 @@ +#include <stc/cstr.h> + +// Olympics multimap example + +struct OlympicsData { int year; const char *city, *country, *date; } ol_data[] = { + {2026, "Milan and Cortina d'Ampezzo", "Italy", "February 6-22"}, + {2022, "Beijing", "China", "February 4-20"}, + {2018, "PyeongChang", "South Korea", "February 9-25"}, + {2014, "Sochi", "Russia", "February 7-23"}, + {2010, "Vancouver", "Canada", "February 12-28"}, + {2006, "Torino", "Italy", "February 10-26"}, + {2002, "Salt Lake City", "United States", "February 8-24"}, + {1998, "Nagano", "Japan", "February 7-22"}, + {1994, "Lillehammer", "Norway", "February 12-27"}, + {1992, "Albertville", "France", "February 8-23"}, + {1988, "Calgary", "Canada", "February 13-28"}, + {1984, "Sarajevo", "Yugoslavia", "February 8-19"}, + {1980, "Lake Placid", "United States", "February 13-24"}, + {1976, "Innsbruck", "Austria", "February 4-15"}, + {1972, "Sapporo", "Japan", "February 3-13"}, + {1968, "Grenoble", "France", "February 6-18"}, + {1964, "Innsbruck", "Austria", "January 29-February 9"}, + {1960, "Squaw Valley", "United States", "February 18-28"}, + {1956, "Cortina d'Ampezzo", "Italy", "January 26 - February 5"}, + {1952, "Oslo", "Norway", "February 14 - 25"}, + {1948, "St. Moritz", "Switzerland", "January 30 - February 8"}, + {1944, "canceled", "canceled", "canceled"}, + {1940, "canceled", "canceled", "canceled"}, + {1936, "Garmisch-Partenkirchen", "Germany", "February 6 - 16"}, + {1932, "Lake Placid", "United States", "February 4 - 15"}, + {1928, "St. Moritz", "Switzerland", "February 11 - 19"}, + {1924, "Chamonix", "France", "January 25 - February 5"}, +}; + +typedef struct { int year; cstr city, date; } OlympicLocation; + +int OlympicLocation_cmp(const OlympicLocation* a, const OlympicLocation* b); +OlympicLocation OlympicLocation_clone(OlympicLocation loc); +void OlympicLocation_drop(OlympicLocation* self); + +// Create a clist<OlympicLocation>, can be sorted by year. +#define i_valclass OlympicLocation // binds _cmp, _clone and _drop. +#define i_tag OL +#define i_extern // define _clist_mergesort() +#include <stc/clist.h> + +// Create a csmap<cstr, clist_OL> where key is country name +#define i_key_str // binds cstr_equ, cstr_hash, cstr_clone, ++ +#define i_valclass clist_OL // binds clist_OL_clone, clist_OL_drop +#define i_tag OL +#include <stc/csmap.h> + +int OlympicLocation_cmp(const OlympicLocation* a, const OlympicLocation* b) { + return a->year - b->year; +} + +OlympicLocation OlympicLocation_clone(OlympicLocation loc) { + loc.city = cstr_clone(loc.city); + loc.date = cstr_clone(loc.date); + return loc; +} +void OlympicLocation_drop(OlympicLocation* self) { + c_drop(cstr, &self->city, &self->date); +} + +int main() +{ + // Define the multimap with destructor defered to when block is completed. + c_auto (csmap_OL, multimap) + { + const clist_OL empty = clist_OL_init(); + + for (size_t i = 0; i < c_arraylen(ol_data); ++i) + { + struct OlympicsData* d = &ol_data[i]; + OlympicLocation loc = {.year = d->year, + .city = cstr_from(d->city), + .date = cstr_from(d->date)}; + // Insert an empty list for each new country, and append the entry to the list. + // If country already exist in map, its list is returned from the insert function. + clist_OL* list = &csmap_OL_insert(&multimap, cstr_from(d->country), empty).ref->second; + clist_OL_push_back(list, loc); + } + // Sort locations by year for each country. + c_foreach (country, csmap_OL, multimap) + clist_OL_sort(&country.ref->second); + + // Print the multimap: + c_foreach (country, csmap_OL, multimap) + { + // Loop the locations for a country sorted by year + c_foreach (loc, clist_OL, country.ref->second) + printf("%s: %d, %s, %s\n", cstr_str(&country.ref->first), + loc.ref->year, + cstr_str(&loc.ref->city), + cstr_str(&loc.ref->date)); + } + } +} diff --git a/misc/examples/music_arc.c b/misc/examples/music_arc.c new file mode 100644 index 00000000..162c4c2f --- /dev/null +++ b/misc/examples/music_arc.c @@ -0,0 +1,68 @@ +// shared_ptr-examples.cpp +// based on https://docs.microsoft.com/en-us/cpp/cpp/how-to-create-and-use-shared-ptr-instances?view=msvc-160 +#include <stc/cstr.h> + +struct Song +{ + cstr artist; + cstr title; +} typedef Song; + +int Song_cmp(const Song* x, const Song* y) + { return cstr_cmp(&x->title, &y->title); } + +Song Song_from(const char* artist, const char* title) + { return (Song){cstr_from(artist), cstr_from(title)}; } + +void Song_drop(Song* s) { + printf("drop: %s\n", cstr_str(&s->title)); + c_drop(cstr, &s->artist, &s->title); +} + +// Define the reference counted type +#define i_type SongArc +#define i_valclass Song +#define i_opt c_no_hash +#include <stc/carc.h> + +// ... and a vector of it +#define i_type SongVec +#define i_valboxed SongArc +#include <stc/cstack.h> + +void example3() +{ + c_auto (SongVec, vec1, vec2) + { + c_forlist (i, Song, { + Song_from("Bob Dylan", "The Times They Are A Changing"), + Song_from("Aretha Franklin", "Bridge Over Troubled Water"), + Song_from("Thalia", "Entre El Mar y Una Estrella") + }) SongVec_emplace(&vec1, *i.ref); + + // Share all entries in vec with vec2, except Bob Dylan. + c_foreach (s, SongVec, vec1) + if (!cstr_equals(&s.ref->get->artist, "Bob Dylan")) + SongVec_push(&vec2, SongArc_clone(*s.ref)); + + // Add a few more to vec2. We can use emplace when creating new entries + SongVec_emplace(&vec2, Song_from("Michael Jackson", "Billie Jean")); + SongVec_emplace(&vec2, Song_from("Rihanna", "Stay")); + // If we use push, we would need to construct the Arc explicitly (as in c++, make_shared): + // SongVec_push(&vec2, SongArc_from(Song_from("Rihanna", "Stay"))); + + // We now have two vectors with some shared, some unique entries. + c_forlist (i, SongVec, {vec1, vec2}) { + puts("VEC:"); + c_foreach (s, SongVec, *i.ref) + printf(" %s - %s, REFS: %ld\n", cstr_str(&s.ref->get->artist), + cstr_str(&s.ref->get->title), + *s.ref->use_count); + } + } // because the shared elem. are ref. counted, they are only dropped once here. +} + +int main() +{ + example3(); +} diff --git a/misc/examples/new_arr.c b/misc/examples/new_arr.c new file mode 100644 index 00000000..871cfae0 --- /dev/null +++ b/misc/examples/new_arr.c @@ -0,0 +1,57 @@ +#include <stc/cstr.h> + +#define i_val int +#include <stc/carr2.h> + +#define i_val int +#include <stc/carr3.h> + +#define i_val_str +#include <stc/carr2.h> + +int main() +{ + int w = 7, h = 5, d = 3; + + c_with (carr2_int volume = carr2_int_new_uninit(w, h), carr2_int_drop(&volume)) + { + int *dat = carr2_int_data(&volume); + for (size_t i = 0; i < carr2_int_size(&volume); ++i) + dat[i] = i; + + for (size_t x = 0; x < volume.xdim; ++x) + for (size_t y = 0; y < volume.ydim; ++y) + printf(" %d", volume.data[x][y]); + puts(""); + + c_foreach (i, carr2_int, volume) + printf(" %d", *i.ref); + puts("\n"); + } + + c_with (carr3_int volume = carr3_int_new_uninit(w, h, d), carr3_int_drop(&volume)) + { + int *dat = carr3_int_data(&volume); + for (size_t i = 0; i < carr3_int_size(&volume); ++i) + dat[i] = i; + + for (size_t x = 0; x < volume.xdim; ++x) + for (size_t y = 0; y < volume.ydim; ++y) + for (size_t z = 0; z < volume.zdim; ++z) + printf(" %d", volume.data[x][y][z]); + puts(""); + + c_foreach (i, carr3_int, volume) + printf(" %d", *i.ref); + puts(""); + } + + c_with (carr2_str text2d = carr2_str_with_size(h, d, cstr_NULL), carr2_str_drop(&text2d)) + { + cstr_assign(&text2d.data[2][1], "hello"); + cstr_assign(&text2d.data[4][0], "world"); + + c_foreach (i, carr2_str, text2d) + printf("line: %s\n", cstr_str(i.ref)); + } +} diff --git a/misc/examples/new_deq.c b/misc/examples/new_deq.c new file mode 100644 index 00000000..39149140 --- /dev/null +++ b/misc/examples/new_deq.c @@ -0,0 +1,61 @@ +#include <stc/cstr.h> +#include <stc/forward.h> + +forward_cdeq(cdeq_i32, int); +forward_cdeq(cdeq_pnt, struct Point); + +struct MyStruct { + cdeq_i32 intvec; + cdeq_pnt pntvec; +} typedef MyStruct; + + +#define i_val int +#define i_opt c_is_forward +#define i_tag i32 +#include <stc/cdeq.h> + +struct Point { int x, y; } typedef Point; +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; +} + +#define i_val Point +#define i_cmp point_cmp +#define i_opt c_is_forward +#define i_tag pnt +#include <stc/cdeq.h> + +#define i_val float +#include <stc/cdeq.h> + +#define i_val_str +#include <stc/cdeq.h> + + +int main() +{ + c_auto (cdeq_i32, vec) + { + cdeq_i32_push_back(&vec, 123); + } + c_auto (cdeq_float, fvec) + { + cdeq_float_push_back(&fvec, 123.3f); + } + c_auto (cdeq_pnt, pvec) + { + cdeq_pnt_push_back(&pvec, (Point){42, 14}); + cdeq_pnt_push_back(&pvec, (Point){32, 94}); + cdeq_pnt_push_front(&pvec, (Point){62, 81}); + cdeq_pnt_sort(&pvec); + c_foreach (i, cdeq_pnt, pvec) + printf(" (%d %d)", i.ref->x, i.ref->y); + puts(""); + } + c_auto (cdeq_str, svec) + { + cdeq_str_emplace_back(&svec, "Hello, friend"); + } +} diff --git a/misc/examples/new_list.c b/misc/examples/new_list.c new file mode 100644 index 00000000..6dbe80b4 --- /dev/null +++ b/misc/examples/new_list.c @@ -0,0 +1,61 @@ +#include <stc/cstr.h> + +forward_clist(clist_i32, int); +forward_clist(clist_pnt, struct Point); + +struct MyStruct { + clist_i32 intlst; + clist_pnt pntlst; +} typedef MyStruct; + +#define i_val int +#define i_opt c_is_forward +#define i_tag i32 +#define i_extern // define _clist_mergesort() +#include <stc/clist.h> + +struct Point { int x, y; } typedef Point; +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; +} + +#define i_val Point +#define i_cmp point_cmp +#define i_opt c_is_forward +#define i_tag pnt +#include <stc/clist.h> + +#define i_val float +#include <stc/clist.h> + +#define i_val_str +#include <stc/clist.h> + + +int main() +{ + c_auto (clist_i32, lst) + clist_i32_push_back(&lst, 123); + + c_auto (clist_pnt, plst) { + c_forlist (i, Point, {{42, 14}, {32, 94}, {62, 81}}) + clist_pnt_push_back(&plst, *i.ref); + + clist_pnt_sort(&plst); + + c_foreach (i, clist_pnt, plst) + printf(" (%d %d)", i.ref->x, i.ref->y); + puts(""); + } + + c_auto (clist_float, flst) { + c_forlist (i, float, {123.3f, 321.2f, -32.2f, 78.2f}) + clist_float_push_back(&flst, *i.ref); + + c_foreach (i, clist_float, flst) printf(" %g", *i.ref); + } + + c_auto (clist_str, slst) + clist_str_emplace_back(&slst, "Hello, friend"); +} diff --git a/misc/examples/new_map.c b/misc/examples/new_map.c new file mode 100644 index 00000000..f43d4217 --- /dev/null +++ b/misc/examples/new_map.c @@ -0,0 +1,73 @@ +#include <stc/cstr.h> +#include <stc/forward.h> + +forward_cmap(cmap_pnt, struct Point, int); + +struct MyStruct { + cmap_pnt pntmap; + cstr name; +} typedef MyStruct; + +// int => int map +#define i_key int +#define i_val int +#include <stc/cmap.h> + +// Point => int map +struct Point { int x, y; } typedef Point; + +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; +} + +// Point => int map +#define i_key Point +#define i_val int +#define i_cmp point_cmp +#define i_hash c_default_hash +#define i_opt c_is_forward +#define i_tag pnt +#include <stc/cmap.h> + +// cstr => cstr map +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +// string set +#define i_key_str +#include <stc/cset.h> + + +int main() +{ + c_auto (cmap_int, map) + c_auto (cmap_pnt, pmap) + c_auto (cmap_str, smap) + c_auto (cset_str, sset) + { + cmap_int_insert(&map, 123, 321); + + c_forlist (i, cmap_pnt_raw, {{{42, 14}, 1}, {{32, 94}, 2}, {{62, 81}, 3}}) + cmap_pnt_insert(&pmap, c_PAIR(i.ref)); + + c_foreach (i, cmap_pnt, pmap) + printf(" (%d, %d: %d)", i.ref->first.x, i.ref->first.y, i.ref->second); + puts(""); + + c_forlist (i, cmap_str_raw, { + {"Hello, friend", "long time no see"}, + {"So long, friend", "see you around"}, + }) cmap_str_emplace(&smap, c_PAIR(i.ref)); + + c_forlist (i, const char*, { + "Hello, friend", + "Nice to see you again", + "So long, friend", + }) cset_str_emplace(&sset, *i.ref); + + c_foreach (i, cset_str, sset) + printf(" %s\n", cstr_str(i.ref)); + } +} diff --git a/misc/examples/new_pque.c b/misc/examples/new_pque.c new file mode 100644 index 00000000..2bb1d729 --- /dev/null +++ b/misc/examples/new_pque.c @@ -0,0 +1,55 @@ +#include <stdio.h> + +#define i_val int +#include <stc/cstack.h> +#define i_val int +#include <stc/cpque.h> + +struct Point { int x, y; } typedef Point; + +int Point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; +} + +#define i_val Point +#define i_cmp Point_cmp +#define i_tag pnt +#include <stc/cpque.h> + + +int main() +{ + c_auto (cstack_int, istk) + { + cstack_int_push(&istk, 123); + cstack_int_push(&istk, 321); + // print + c_foreach (i, cstack_int, istk) + printf(" %d", *i.ref); + puts(""); + } + c_auto (cpque_pnt, pque) + { + cpque_pnt_push(&pque, (Point){23, 80}); + cpque_pnt_push(&pque, (Point){12, 32}); + cpque_pnt_push(&pque, (Point){54, 74}); + cpque_pnt_push(&pque, (Point){12, 62}); + // print + while (!cpque_pnt_empty(&pque)) { + const cpque_pnt_value *v = cpque_pnt_top(&pque); + printf(" (%d,%d)", v->x, v->y); + cpque_pnt_pop(&pque); + } + puts(""); + } + c_auto (cpque_int, ique) + { + cpque_int_push(&ique, 123); + cpque_int_push(&ique, 321); + // print + for (size_t i=0; i<cpque_int_size(&ique); ++i) + printf(" %d", ique.data[i]); + puts(""); + } +} diff --git a/misc/examples/new_queue.c b/misc/examples/new_queue.c new file mode 100644 index 00000000..bc7a95c9 --- /dev/null +++ b/misc/examples/new_queue.c @@ -0,0 +1,45 @@ +#include <stc/crandom.h> +#include <stc/forward.h> +#include <stdio.h> +#include <time.h> + +forward_cqueue(cqueue_pnt, struct Point); + +struct Point { int x, y; } typedef Point; +int point_cmp(const Point* a, const Point* b) { + int c = c_default_cmp(&a->x, &b->x); + return c ? c : c_default_cmp(&a->y, &b->y); +} +#define i_val Point +#define i_cmp point_cmp +#define i_opt c_is_forward +#define i_tag pnt +#include <stc/cqueue.h> + +#define i_type IQ +#define i_val int +#include <stc/cqueue.h> + +int main() { + int n = 50000000; + stc64_t rng = stc64_new(time(NULL)); + stc64_uniform_t dist = stc64_uniform_new(0, n); + + c_auto (IQ, Q) + { + // Push eight million random numbers onto the queue. + c_forrange (n) + IQ_push(&Q, stc64_uniform(&rng, &dist)); + + // Push or pop on the queue 50 million times + printf("befor: size %" c_ZU ", capacity %" c_ZU "\n", IQ_size(&Q), IQ_capacity(&Q)); + c_forrange (n) { + int r = stc64_uniform(&rng, &dist); + if (r & 3) + IQ_push(&Q, r); + else + IQ_pop(&Q); + } + printf("after: size %" c_ZU ", capacity %" c_ZU "\n", IQ_size(&Q), IQ_capacity(&Q)); + } +} diff --git a/misc/examples/new_smap.c b/misc/examples/new_smap.c new file mode 100644 index 00000000..c77aa185 --- /dev/null +++ b/misc/examples/new_smap.c @@ -0,0 +1,77 @@ +#include <stc/cstr.h> +#include <stc/forward.h> + +forward_csmap(PMap, struct Point, int); + +// Use forward declared PMap in struct +struct MyStruct { + PMap pntmap; + cstr name; +} typedef MyStruct; + +// int => int map +#define i_key int +#define i_val int +#include <stc/csmap.h> + +// Point => int map +struct Point { int x, y; } typedef Point; +int point_cmp(const Point* a, const Point* b) { + int c = a->x - b->x; + return c ? c : a->y - b->y; +} + +#define i_type PMap +#define i_key Point +#define i_val int +#define i_cmp point_cmp +#define i_opt c_is_forward +#include <stc/csmap.h> + +// cstr => cstr map +#define i_type SMap +#define i_key_str +#define i_val_str +#include <stc/csmap.h> + +// cstr set +#define i_type SSet +#define i_key_str +#include <stc/csset.h> + + +int main() +{ + c_auto (csmap_int, imap) { + csmap_int_insert(&imap, 123, 321); + } + + c_auto (PMap, pmap) { + c_forlist (i, PMap_value, { + {{42, 14}, 1}, + {{32, 94}, 2}, + {{62, 81}, 3}, + }) PMap_insert(&pmap, c_PAIR(i.ref)); + + c_forpair (p, i, PMap, pmap) + printf(" (%d,%d: %d)", _.p->x, _.p->y, *_.i); + puts(""); + } + + c_auto (SMap, smap) { + c_forlist (i, SMap_raw, { + {"Hello, friend", "this is the mapped value"}, + {"The brown fox", "jumped"}, + {"This is the time", "for all good things"}, + }) SMap_emplace(&smap, c_PAIR(i.ref)); + + c_forpair (i, j, SMap, smap) + printf(" (%s: %s)\n", cstr_str(_.i), cstr_str(_.j)); + } + + c_auto (SSet, sset) { + SSet_emplace(&sset, "Hello, friend"); + SSet_emplace(&sset, "Goodbye, foe"); + printf("Found? %s\n", SSet_contains(&sset, "Hello, friend") ? "true" : "false"); + } +} diff --git a/misc/examples/new_sptr.c b/misc/examples/new_sptr.c new file mode 100644 index 00000000..2c6b28d6 --- /dev/null +++ b/misc/examples/new_sptr.c @@ -0,0 +1,72 @@ +#include <stc/cstr.h> + +typedef struct { cstr name, last; } Person; +Person Person_make(const char* name, const char* last); +Person Person_clone(Person p); +void Person_drop(Person* p); +int Person_cmp(const Person* a, const Person* b); +uint64_t Person_hash(const Person* p); + +#define i_type PersonArc +#define i_valclass Person // "class" ensure Person_drop will be called +#define i_cmp Person_cmp // enable carc object comparisons (not ptr to obj) +#define i_hash Person_hash // enable carc object hash (not ptr to obj) +#include <stc/carc.h> + +#define i_type IPtr +#define i_val int +#define i_valdrop(x) printf("drop: %d\n", *x) +#include <stc/carc.h> + +#define i_type IPStack +#define i_valboxed IPtr +#include <stc/cstack.h> + +#define i_type PASet +#define i_valboxed PersonArc +#include <stc/cset.h> + + +Person Person_make(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} +int Person_cmp(const Person* a, const Person* b) { + return cstr_cmp(&a->name, &b->name); +} +uint64_t Person_hash(const Person* p) { + return cstr_hash(&p->name); +} +Person Person_clone(Person p) { + p.name = cstr_clone(p.name), p.last = cstr_clone(p.last); + return p; +} +void Person_drop(Person* p) { + printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last)); + c_drop(cstr, &p->name, &p->last); +} + + +int main(void) { + c_auto (PersonArc, p, q, r, s) + { + puts("Ex1"); + p = PersonArc_from(Person_make("John", "Smiths")); + q = PersonArc_clone(p); // share + r = PersonArc_clone(p); + s = PersonArc_from(Person_clone(*p.get)); // deep copy + printf("%s %s: refs %ld\n", cstr_str(&p.get->name), cstr_str(&p.get->last), *p.use_count); + } + c_auto (IPStack, vec) + { + puts("Ex2"); + IPStack_push(&vec, IPtr_from(10)); + IPStack_push(&vec, IPtr_from(20)); + IPStack_emplace(&vec, 30); // same as IPStack_push(&vec, IPtr_from(30)); + IPStack_push(&vec, IPtr_clone(*IPStack_back(&vec))); + IPStack_push(&vec, IPtr_clone(*IPStack_front(&vec))); + + c_foreach (i, IPStack, vec) + printf(" (%d: refs %ld)", *i.ref->get, *i.ref->use_count); + puts(""); + } +} diff --git a/misc/examples/new_vec.c b/misc/examples/new_vec.c new file mode 100644 index 00000000..84e4c7b2 --- /dev/null +++ b/misc/examples/new_vec.c @@ -0,0 +1,58 @@ +#include <stc/cstr.h> +#include <stc/forward.h> + +forward_cvec(cvec_i32, int); +forward_cvec(cvec_pnt, struct Point); + +struct MyStruct { + cvec_i32 intvec; + cvec_pnt pntvec; +} typedef MyStruct; + +#define i_val int +#define i_opt c_is_forward +#define i_tag i32 +#include <stc/cvec.h> + +struct Point { int x, y; } typedef Point; +int point_cmp(const Point* a, const Point* b) { + int c = c_default_cmp(&a->x, &b->x); + return c ? c : c_default_cmp(&a->y, &b->y); +} + +#define i_val Point +//#define i_cmp point_cmp +#define i_less(a, b) a->x < b->x || (a->x == b->x && a->y < b->y) +#define i_opt c_is_forward +#define i_tag pnt +#include <stc/cvec.h> + +#define i_val float +#include <stc/cvec.h> + +#define i_val_str +#include <stc/cvec.h> + + +int main() +{ + c_auto (cvec_i32, vec) + c_auto (cvec_float, fvec) + c_auto (cvec_pnt, pvec) + c_auto (cvec_str, svec) + { + cvec_i32_push(&vec, 123); + cvec_float_push(&fvec, 123.3f); + + cvec_pnt_push(&pvec, (Point){42, 14}); + cvec_pnt_push(&pvec, (Point){32, 94}); + cvec_pnt_push(&pvec, (Point){62, 81}); + cvec_pnt_push(&pvec, (Point){32, 91}); + cvec_pnt_sort(&pvec); + c_foreach (i, cvec_pnt, pvec) + printf(" (%d %d)", i.ref->x, i.ref->y); + puts(""); + + cvec_str_emplace(&svec, "Hello, friend"); + } +} diff --git a/misc/examples/person_arc.c b/misc/examples/person_arc.c new file mode 100644 index 00000000..a7bf2a6f --- /dev/null +++ b/misc/examples/person_arc.c @@ -0,0 +1,74 @@ +/* cbox: heap allocated boxed type */ +#include <stc/cstr.h> + +typedef struct { cstr name, last; } Person; + +Person Person_make(const char* name, const char* last) { + return (Person){.name = cstr_from(name), .last = cstr_from(last)}; +} + +int Person_cmp(const Person* a, const Person* b) { + int c = cstr_cmp(&a->name, &b->name); + return c ? c : cstr_cmp(&a->last, &b->last); +} + +uint64_t Person_hash(const Person* a) { + return cstr_hash(&a->name) ^ cstr_hash(&a->last); +} + +Person Person_clone(Person p) { + p.name = cstr_clone(p.name); + p.last = cstr_clone(p.last); + return p; +} + +void Person_drop(Person* p) { + printf("drop: %s %s\n", cstr_str(&p->name), cstr_str(&p->last)); + c_drop(cstr, &p->name, &p->last); +} + +#define i_type PSPtr +#define i_valclass Person // ensure Person_drop +#define i_cmp Person_cmp // specify object cmp, instead of ptr cmp for arc. +#include <stc/carc.h> + +#define i_type Persons +#define i_valboxed PSPtr // binds PSPtr_cmp, PSPtr_drop... +#include <stc/cvec.h> + + +int main() +{ + c_auto (Persons, vec) + c_auto (PSPtr, p, q) + { + p = PSPtr_from(Person_make("Laura", "Palmer")); + + // We want a deep copy -- PSPtr_clone(p) only shares! + q = PSPtr_from(Person_clone(*p.get)); + cstr_assign(&q.get->name, "Leland"); + + printf("orig: %s %s\n", cstr_str(&p.get->name), cstr_str(&p.get->last)); + printf("copy: %s %s\n", cstr_str(&q.get->name), cstr_str(&q.get->last)); + + // Use Persons_emplace to implicitly call PSPtr_make on the argument. + // No need to do: Persons_push(&vec, PSPtr_make(Person_make("Audrey", "Home"))); + Persons_emplace(&vec, Person_make("Audrey", "Home")); + Persons_emplace(&vec, Person_make("Dale", "Cooper")); + + // Clone/share p and q to the vector + c_forlist (i, PSPtr, {p, q}) + Persons_push(&vec, PSPtr_clone(*i.ref)); + + c_foreach (i, Persons, vec) + printf("%s %s\n", cstr_str(&i.ref->get->name), cstr_str(&i.ref->get->last)); + puts(""); + + // Look-up Audrey! + c_with (Person a = Person_make("Audrey", "Home"), Person_drop(&a)) { + const PSPtr *v = Persons_get(&vec, a); + if (v) printf("found: %s %s\n", cstr_str(&v->get->name), cstr_str(&v->get->last)); + } + puts(""); + } +} diff --git a/misc/examples/phonebook.c b/misc/examples/phonebook.c new file mode 100644 index 00000000..be068409 --- /dev/null +++ b/misc/examples/phonebook.c @@ -0,0 +1,82 @@ +// The MIT License (MIT) +// Copyright (c) 2018 Maksim Andrianov +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +// Program to emulates the phone book. + +#include <stc/cstr.h> + +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +#define i_key_str +#include <stc/cset.h> + +void print_phone_book(cmap_str phone_book) +{ + c_foreach (i, cmap_str, phone_book) + printf("%s\t- %s\n", cstr_str(&i.ref->first), cstr_str(&i.ref->second)); +} + +int main(int argc, char **argv) +{ + c_auto (cset_str, names) { + c_forlist (i, const char*, {"Hello", "Cool", "True"}) + cset_str_emplace(&names, *i.ref); + + c_foreach (i, cset_str, names) + printf("%s ", cstr_str(i.ref)); + puts(""); + } + + c_auto (cmap_str, phone_book) { + c_forlist (i, cmap_str_raw, { + {"Lilia Friedman", "(892) 670-4739"}, + {"Tariq Beltran", "(489) 600-7575"}, + {"Laiba Juarez", "(303) 885-5692"}, + {"Elliott Mooney", "(945) 616-4482"}, + }) cmap_str_emplace(&phone_book, c_PAIR(i.ref)); + + printf("Phone book:\n"); + print_phone_book(phone_book); + + cmap_str_emplace(&phone_book, "Zak Byers", "(551) 396-1880"); + cmap_str_emplace(&phone_book, "Zak Byers", "(551) 396-1990"); + + printf("\nPhone book after adding Zak Byers:\n"); + print_phone_book(phone_book); + + if (cmap_str_contains(&phone_book, "Tariq Beltran")) + printf("\nTariq Beltran is in phone book\n"); + + cmap_str_erase(&phone_book, "Tariq Beltran"); + cmap_str_erase(&phone_book, "Elliott Mooney"); + + printf("\nPhone book after erasing Tariq and Elliott:\n"); + print_phone_book(phone_book); + + cmap_str_emplace_or_assign(&phone_book, "Zak Byers", "(555) 396-188"); + + printf("\nPhone book after update phone of Zak Byers:\n"); + print_phone_book(phone_book); + } + puts("done"); +} diff --git a/misc/examples/prime.c b/misc/examples/prime.c new file mode 100644 index 00000000..287fb69b --- /dev/null +++ b/misc/examples/prime.c @@ -0,0 +1,51 @@ +#include <stdio.h> +#include <math.h> +#include <time.h> +#include <stc/cbits.h> +#include <stc/views.h> + +cbits sieveOfEratosthenes(size_t n) +{ + cbits bits = cbits_with_size(n/2 + 1, true); + size_t q = (size_t) sqrt((double) n) + 1; + for (size_t i = 3; i < q; i += 2) { + size_t j = i; + for (; j < n; j += 2) { + if (cbits_test(&bits, j>>1)) { + i = j; + break; + } + } + for (size_t j = i*i; j < n; j += i*2) + cbits_reset(&bits, j>>1); + } + return bits; +} + +int main(void) +{ + size_t n = 1000000000; + printf("computing prime numbers up to %" c_ZU "\n", n); + + clock_t t1 = clock(); + c_with (cbits primes = sieveOfEratosthenes(n + 1), cbits_drop(&primes)) { + puts("done"); + size_t np = cbits_count(&primes); + clock_t t2 = clock(); + + printf("number of primes: %" c_ZU ", time: %f\n", np, (t2 - t1) / (float)CLOCKS_PER_SEC); + puts("Show all the primes in the range [2, 1000):"); + printf("2"); + c_forrange (i, 3, 1000, 2) + if (cbits_test(&primes, i>>1)) printf(" %lld", i); + puts(""); + + puts("Show the last 50 primes using a temporary crange generator:"); + c_forfilter (i, crange, crange_literal(n - 1, 0, -2) + , cbits_test(&primes, *i.ref>>1) + , c_flt_take(i, 50)) { + printf("%lld ", *i.ref); + if (i.count % 10 == 0) puts(""); + } + } +} diff --git a/misc/examples/priority.c b/misc/examples/priority.c new file mode 100644 index 00000000..f6e63205 --- /dev/null +++ b/misc/examples/priority.c @@ -0,0 +1,35 @@ + +#include <stdio.h> +#include <time.h> +#include <stc/crandom.h> + +#define i_val int64_t +#define i_cmp -c_default_cmp // min-heap (increasing values) +#define i_tag i +#include <stc/cpque.h> + +int main() { + size_t N = 10000000; + stc64_t rng = stc64_new(time(NULL)); + stc64_uniform_t dist = stc64_uniform_new(0, N * 10); + c_auto (cpque_i, heap) + { + // Push ten million random numbers to priority queue + printf("Push %" c_ZU " numbers\n", N); + c_forrange (N) + cpque_i_push(&heap, stc64_uniform(&rng, &dist)); + + // push some negative numbers too. + c_forlist (i, int, {-231, -32, -873, -4, -343}) + cpque_i_push(&heap, *i.ref); + + c_forrange (N) + cpque_i_push(&heap, stc64_uniform(&rng, &dist)); + + puts("Extract the hundred smallest."); + c_forrange (100) { + printf("%" PRId64 " ", *cpque_i_top(&heap)); + cpque_i_pop(&heap); + } + } +} diff --git a/misc/examples/queue.c b/misc/examples/queue.c new file mode 100644 index 00000000..f39c4b8b --- /dev/null +++ b/misc/examples/queue.c @@ -0,0 +1,31 @@ +#include <stc/crandom.h> +#include <stdio.h> + +#define i_val int +#define i_tag i +#include <stc/cqueue.h> + +int main() { + int n = 100000000; + stc64_uniform_t dist; + stc64_t rng = stc64_new(1234); + dist = stc64_uniform_new(0, n); + + c_auto (cqueue_i, queue) + { + // Push ten million random numbers onto the queue. + c_forrange (n) + cqueue_i_push(&queue, stc64_uniform(&rng, &dist)); + + // Push or pop on the queue ten million times + printf("%d\n", n); + c_forrange (n) { // forrange uses initial n only. + int r = stc64_uniform(&rng, &dist); + if (r & 1) + ++n, cqueue_i_push(&queue, r); + else + --n, cqueue_i_pop(&queue); + } + printf("%d, %" c_ZU "\n", n, cqueue_i_size(&queue)); + } +} diff --git a/misc/examples/random.c b/misc/examples/random.c new file mode 100644 index 00000000..fe64290d --- /dev/null +++ b/misc/examples/random.c @@ -0,0 +1,45 @@ +#include <stdio.h> +#include <time.h> +#include <stc/crandom.h> + +int main() +{ + const size_t N = 1000000000; + const uint64_t seed = time(NULL), range = 1000000; + stc64_t rng = stc64_new(seed); + + uint64_t sum; + clock_t diff, before; + + printf("Compare speed of full and unbiased ranged random numbers...\n"); + sum = 0; + before = clock(); + c_forrange (N) { + sum += (uint32_t)stc64_rand(&rng); + } + diff = clock() - before; + printf("full range\t\t: %f secs, %" c_ZU ", avg: %f\n", + (float)diff / CLOCKS_PER_SEC, N, (double)sum / N); + + stc64_uniform_t dist1 = stc64_uniform_new(0, range); + rng = stc64_new(seed); + sum = 0; + before = clock(); + c_forrange (N) { + sum += stc64_uniform(&rng, &dist1); // unbiased + } + diff = clock() - before; + printf("unbiased 0-%" PRIu64 "\t: %f secs, %" c_ZU ", avg: %f\n", + range, (float)diff/CLOCKS_PER_SEC, N, (double)sum / N); + + sum = 0; + rng = stc64_new(seed); + before = clock(); + c_forrange (N) { + sum += stc64_rand(&rng) % (range + 1); // biased + } + diff = clock() - before; + printf("biased 0-%" PRIu64 " \t: %f secs, %" c_ZU ", avg: %f\n", + range, (float)diff / CLOCKS_PER_SEC, N, (double)sum / N); + +} diff --git a/misc/examples/rawptr_elements.c b/misc/examples/rawptr_elements.c new file mode 100644 index 00000000..4b3d2056 --- /dev/null +++ b/misc/examples/rawptr_elements.c @@ -0,0 +1,55 @@ +#include <stc/ccommon.h> +#include <stdio.h> + +#include <stc/cstr.h> +// Map of cstr => int64 pointers +typedef int64_t inttype; + +// Do it without cbox: +#define i_type SIPtrMap +#define i_key_str +#define i_val inttype* +#define i_valraw inttype +#define i_valfrom(raw) c_new(inttype, raw) +#define i_valto(x) **x +#define i_valclone(x) c_new(inttype, *x) +#define i_valdrop(x) c_free(*x) +#include <stc/cmap.h> + +// With cbox: +#define i_type IBox +#define i_val int +#include <stc/cbox.h> //<stc/carc.h> + +#define i_type SIBoxMap +#define i_key_str +#define i_valboxed IBox +#include <stc/cmap.h> + +int main() +{ + c_auto (SIPtrMap, map, m1) + c_auto (SIBoxMap, m2) + { + printf("\nMap with pointer elements:\n"); + SIPtrMap_insert(&map, cstr_from("testing"), c_new(inttype, 1)); + SIPtrMap_insert(&map, cstr_from("done"), c_new(inttype, 2)); + + // Emplace: implicit key, val construction: + SIPtrMap_emplace(&map, "hello", 3); + SIPtrMap_emplace(&map, "goodbye", 4); + + m1 = SIPtrMap_clone(map); + + c_forpair (name, number, SIPtrMap, m1) + printf("%s: %" PRId64 "\n", cstr_str(_.name), **_.number); + + + puts("\nIBox map:"); + SIBoxMap_insert(&m2, cstr_from("Hello"), IBox_make(123)); + SIBoxMap_emplace(&m2, "World", 999); + c_forpair (name, number, SIBoxMap, m2) + printf("%s: %d\n", cstr_str(_.name), *_.number->get); + puts(""); + } +} diff --git a/misc/examples/read.c b/misc/examples/read.c new file mode 100644 index 00000000..4efdcfeb --- /dev/null +++ b/misc/examples/read.c @@ -0,0 +1,25 @@ +#include <stc/cstr.h> +#define i_val_str +#include <stc/cvec.h> +#include <errno.h> + +cvec_str read_file(const char* name) +{ + cvec_str vec = cvec_str_init(); + c_with (FILE* f = fopen(name, "r"), fclose(f)) + c_with (cstr line = cstr_NULL, cstr_drop(&line)) + while (cstr_getline(&line, f)) + cvec_str_push(&vec, cstr_clone(line)); + return vec; +} + +int main() +{ + int n = 0; + c_with (cvec_str vec = read_file(__FILE__), cvec_str_drop(&vec)) + c_foreach (i, cvec_str, vec) + printf("%5d: %s\n", ++n, cstr_str(i.ref)); + + if (errno) + printf("error: read_file(" __FILE__ "). errno: %d\n", errno); +} diff --git a/misc/examples/regex1.c b/misc/examples/regex1.c new file mode 100644 index 00000000..7a22220d --- /dev/null +++ b/misc/examples/regex1.c @@ -0,0 +1,30 @@ +#define i_extern +#include <stc/cregex.h> + +int main(int argc, char* argv[]) +{ + if (argc <= 1) { + printf("Usage: regex1 -i\n"); + return 0; + } + c_auto (cstr, input) + c_auto (cregex, float_expr) + { + int res = cregex_compile(&float_expr, "^[+-]?[0-9]+((\\.[0-9]*)?|\\.[0-9]+)$", CREG_DEFAULT); + // Until "q" is given, ask for another number + if (res > 0) while (true) + { + printf("Enter a double precision number (q for quit): "); + cstr_getline(&input, stdin); + + // Exit when the user inputs q + if (cstr_equals(&input, "q")) + break; + + if (cregex_is_match(&float_expr, cstr_str(&input))) + printf("Input is a float\n"); + else + printf("Invalid input : Not a float\n"); + } + } +} diff --git a/misc/examples/regex2.c b/misc/examples/regex2.c new file mode 100644 index 00000000..dbf6aae4 --- /dev/null +++ b/misc/examples/regex2.c @@ -0,0 +1,32 @@ +#define i_extern +#include <stc/cregex.h> + +int main() +{ + struct { const char *pattern, *input; } s[] = { + {"(\\d\\d\\d\\d)[-_](1[0-2]|0[1-9])[-_](3[01]|[12][0-9]|0[1-9])", + "date: 2024-02-29 leapyear day, christmas eve is on 2022-12-24." + }, + {"(https?://|ftp://|www\\.)([0-9A-Za-z@:%_+~#=-]+\\.)+([a-z][a-z][a-z]?)(/[/0-9A-Za-z\\.@:%_+~#=\\?&-]*)?", + "https://en.cppreference.com/w/cpp/regex/regex_search" + }, + {"!((abc|123)+)!", "!123abcabc!"} + }; + + c_auto (cregex, re) + c_forrange (i, c_arraylen(s)) + { + int res = cregex_compile(&re, s[i].pattern, CREG_DEFAULT); + if (res < 0) { + printf("error in regex pattern: %d\n", res); + continue; + } + printf("input: %s\n", s[i].input); + + c_formatch (j, &re, s[i].input) { + c_forrange (k, cregex_captures(&re)) + printf(" submatch %lld: %.*s\n", k, c_ARGSV(j.match[k])); + puts(""); + } + } +} diff --git a/misc/examples/regex_match.c b/misc/examples/regex_match.c new file mode 100644 index 00000000..376b002e --- /dev/null +++ b/misc/examples/regex_match.c @@ -0,0 +1,34 @@ +#define i_extern +#include <stc/cregex.h> +#include <stc/csview.h> +#define i_val float +#include <stc/cstack.h> + +int main() +{ + // Lets find the first sequence of digits in a string + const char *str = "Hello numeric world, there are 24 hours in a day, 3600 seconds in an hour." + " Around 365.25 days a year, and 52 weeks in a year." + " Boltzmann const: 1.38064852E-23, is very small." + " Bohrradius is 5.29177210903e-11, and Avogadros number is 6.02214076e23."; + + c_auto (cregex, re) + c_auto (cstack_float, vec) + c_auto (cstr, nums) + { + const char* pattern = "[+-]?([0-9]*\\.)?\\d+([Ee][+-]?\\d+)?"; + int res = cregex_compile(&re, pattern, CREG_DEFAULT); + printf("%d: %s\n", res, pattern); + + // extract and convert all numbers in str to floats + c_formatch (i, &re, str) + cstack_float_push(&vec, atof(i.match[0].str)); + + c_foreach (i, cstack_float, vec) + printf(" %g\n", *i.ref); + + // extracts the numbers only to a comma separated string. + nums = cregex_replace_sv(&re, csview_from(str), " $0,", 0, NULL, CREG_R_STRIP); + printf("\n%s\n", cstr_str(&nums)); + } +} diff --git a/misc/examples/regex_replace.c b/misc/examples/regex_replace.c new file mode 100644 index 00000000..e296dfd8 --- /dev/null +++ b/misc/examples/regex_replace.c @@ -0,0 +1,53 @@ +#define i_extern +#include <stc/cregex.h> +#include <stc/csview.h> + +bool add_10_years(int i, csview match, cstr* out) { + if (i == 1) { // group 1 matches year + int year; + sscanf(match.str, "%4d", &year); // scan 4 chars only + cstr_printf(out, "%04d", year + 10); + return true; + } + return false; +} + +int main() +{ + const char* pattern = "\\b(\\d\\d\\d\\d)-(1[0-2]|0[1-9])-(3[01]|[12][0-9]|0[1-9])\\b"; + const char* input = "start date: 2015-12-31, end date: 2022-02-28"; + + c_auto (cstr, str) + { + printf("INPUT: %s\n", input); + + /* replace with a fixed string, extended all-in-one call: */ + cstr_take(&str, cregex_replace_pattern(pattern, input, "YYYY-MM-DD")); + printf("fixed: %s\n", cstr_str(&str)); + + /* US date format, and add 10 years to dates: */ + cstr_take(&str, cregex_replace_pattern_n(pattern, input, "$1/$3/$2", 0, add_10_years, CREG_DEFAULT)); + printf("us+10: %s\n", cstr_str(&str)); + + /* Wrap first date inside []: */ + cstr_take(&str, cregex_replace_pattern_n(pattern, input, "[$0]", 1, NULL, CREG_DEFAULT)); + printf("brack: %s\n", cstr_str(&str)); + + /* Shows how to compile RE separately */ + c_with (cregex re = cregex_from(pattern, CREG_DEFAULT), cregex_drop(&re)) { + if (cregex_captures(&re) == 0) + continue; /* break c_with */ + /* European date format. */ + cstr_take(&str, cregex_replace(&re, input, "$3.$2.$1")); + printf("euros: %s\n", cstr_str(&str)); + + /* Strip out everything but the matches */ + cstr_take(&str, cregex_replace_sv(&re, csview_from(input), "$3.$2.$1;", 0, NULL, CREG_R_STRIP)); + printf("strip: %s\n", cstr_str(&str)); + } + + /* Wrap all words in ${} */ + cstr_take(&str, cregex_replace_pattern("[a-z]+", "52 apples and 31 mangoes", "$${$0}")); + printf("curly: %s\n", cstr_str(&str)); + } +} diff --git a/misc/examples/replace.c b/misc/examples/replace.c new file mode 100644 index 00000000..15cf3bae --- /dev/null +++ b/misc/examples/replace.c @@ -0,0 +1,34 @@ +#include <stc/cstr.h> + +int main () +{ + const char *base = "this is a test string."; + const char *s2 = "n example"; + const char *s3 = "sample phrase"; + + // replace signatures used in the same order as described above: + + // Ustring positions: 0123456789*123456789*12345 + cstr s = cstr_from(base); // "this is a test string." + cstr m = cstr_clone(s); + c_defer (cstr_drop(&s), cstr_drop(&m)) { + cstr_append(&m, cstr_str(&m)); + cstr_append(&m, cstr_str(&m)); + printf("%s\n", cstr_str(&m)); + + cstr_replace_at(&s, 9, 5, s2); // "this is an example string." (1) + printf("(1) %s\n", cstr_str(&s)); + + cstr_replace_at_sv(&s, 19, 6, c_SV(s3+7, 6)); // "this is an example phrase." (2) + printf("(2) %s\n", cstr_str(&s)); + + cstr_replace_at(&s, 8, 10, "just a"); // "this is just a phrase." (3) + printf("(3) %s\n", cstr_str(&s)); + + cstr_replace_at_sv(&s, 8, 6, c_SV("a shorty", 7)); // "this is a short phrase." (4) + printf("(4) %s\n", cstr_str(&s)); + + cstr_replace_at(&s, 22, 1, "!!!"); // "this is a short phrase!!!" (5) + printf("(5) %s\n", cstr_str(&s)); + } +} diff --git a/misc/examples/shape.c b/misc/examples/shape.c new file mode 100644 index 00000000..a17208ef --- /dev/null +++ b/misc/examples/shape.c @@ -0,0 +1,159 @@ +// Demo of typesafe polymorphism in C99, using STC. + +#include <stdlib.h> +#include <stdio.h> +#include <stc/ccommon.h> + +#define c_dyn_cast(T, s) \ + (&T##_api == (s)->api ? (T*)(s) : (T*)0) + +// Shape definition +// ============================================================ + +typedef struct { + float x, y; +} Point; + +typedef struct Shape Shape; + +struct ShapeAPI { + void (*drop)(Shape*); + void (*draw)(const Shape*); +}; + +struct Shape { + struct ShapeAPI* api; + uint32_t color; + uint16_t style; + uint8_t thickness; + uint8_t hardness; +}; + +void Shape_drop(Shape* shape) +{ + printf("shape destructed\n"); +} + +void Shape_delete(Shape* shape) +{ + if (shape) { + shape->api->drop(shape); + c_free(shape); + } +} + +// Triangle implementation +// ============================================================ + +typedef struct { + Shape shape; + Point p[3]; +} Triangle; + +static struct ShapeAPI Triangle_api; + + +Triangle Triangle_from(Point a, Point b, Point c) +{ + Triangle t = {{.api=&Triangle_api}, .p={a, b, c}}; + return t; +} + +static void Triangle_draw(const Shape* shape) +{ + const Triangle* self = c_dyn_cast(Triangle, shape); + printf("Triangle : (%g,%g), (%g,%g), (%g,%g)\n", + self->p[0].x, self->p[0].y, + self->p[1].x, self->p[1].y, + self->p[2].x, self->p[2].y); +} + +static struct ShapeAPI Triangle_api = { + .drop = Shape_drop, + .draw = Triangle_draw, +}; + +// Polygon implementation +// ============================================================ + +#define i_type PointVec +#define i_val Point +#include <stc/cstack.h> + +typedef struct { + Shape shape; + PointVec points; +} Polygon; + +static struct ShapeAPI Polygon_api; + + +Polygon Polygon_init(void) +{ + Polygon p = {{.api=&Polygon_api}, .points=PointVec_init()}; + return p; +} + +void Polygon_addPoint(Polygon* self, Point p) +{ + PointVec_push(&self->points, p); +} + +static void Polygon_drop(Shape* shape) +{ + Polygon* self = c_dyn_cast(Polygon, shape); + printf("poly destructed\n"); + PointVec_drop(&self->points); + Shape_drop(shape); +} + +static void Polygon_draw(const Shape* shape) +{ + const Polygon* self = c_dyn_cast(Polygon, shape); + printf("Polygon :"); + c_foreach (i, PointVec, self->points) + printf(" (%g,%g)", i.ref->x, i.ref->y); + puts(""); +} + +static struct ShapeAPI Polygon_api = { + .drop = Polygon_drop, + .draw = Polygon_draw, +}; + +// Test +// ============================================================ + +#define i_type Shapes +#define i_val Shape* +#define i_valdrop(x) Shape_delete(*x) +#include <stc/cstack.h> + +void testShape(const Shape* shape) +{ + shape->api->draw(shape); +} + + +int main(void) +{ + c_auto (Shapes, shapes) + { + Triangle* tri1 = c_new(Triangle, Triangle_from((Point){5, 7}, (Point){12, 7}, (Point){12, 20})); + Polygon* pol1 = c_new(Polygon, Polygon_init()); + Polygon* pol2 = c_new(Polygon, Polygon_init()); + + c_forlist (i, Point, {{50, 72}, {123, 73}, {127, 201}, {828, 333}}) + Polygon_addPoint(pol1, *i.ref); + + c_forlist (i, Point, {{5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}}) + Polygon_addPoint(pol2, *i.ref); + + Shapes_push(&shapes, &tri1->shape); + Shapes_push(&shapes, &pol1->shape); + Shapes_push(&shapes, &pol2->shape); + + c_foreach (i, Shapes, shapes) + testShape(*i.ref); + } +} diff --git a/misc/examples/shape.cpp b/misc/examples/shape.cpp new file mode 100644 index 00000000..ea1f53d2 --- /dev/null +++ b/misc/examples/shape.cpp @@ -0,0 +1,122 @@ +// Demo of polymorphism in C++ + +#include <iostream> +#include <memory> +#include <vector> + +// Shape definition +// ============================================================ + +struct Point { + float x, y; +}; + +std::ostream& operator<<(std::ostream& os, const Point& p) { + os << " (" << p.x << "," << p.y << ")"; + return os; +} + +struct Shape { + virtual ~Shape(); + virtual void draw() const = 0; + + uint32_t color; + uint16_t style; + uint8_t thickness; + uint8_t hardness; +}; + +Shape::~Shape() +{ + std::cout << "base destructed" << std::endl; +} + +// Triangle implementation +// ============================================================ + +struct Triangle : public Shape +{ + Triangle(Point a, Point b, Point c); + void draw() const override; + + private: Point p[3]; +}; + + +Triangle::Triangle(Point a, Point b, Point c) + : p{a, b, c} {} + +void Triangle::draw() const +{ + std::cout << "Triangle :" + << p[0] << p[1] << p[2] + << std::endl; +} + + +// Polygon implementation +// ============================================================ + + +struct Polygon : public Shape +{ + ~Polygon(); + void draw() const override; + void addPoint(const Point& p); + + private: std::vector<Point> points; +}; + + +void Polygon::addPoint(const Point& p) +{ + points.push_back(p); +} + +Polygon::~Polygon() +{ + std::cout << "poly destructed" << std::endl; +} + +void Polygon::draw() const +{ + std::cout << "Polygon :"; + for (auto& p : points) + std::cout << p ; + std::cout << std::endl; +} + + +// Test +// ============================================================ + +void testShape(const Shape* shape) +{ + shape->draw(); +} + +#include <array> + +int main(void) +{ + std::vector<std::unique_ptr<Shape>> shapes; + + auto tri1 = std::make_unique<Triangle>(Point{5, 7}, Point{12, 7}, Point{12, 20}); + auto pol1 = std::make_unique<Polygon>(); + auto pol2 = std::make_unique<Polygon>(); + + for (auto& p: std::array<Point, 4> + {{{50, 72}, {123, 73}, {127, 201}, {828, 333}}}) + pol1->addPoint(p); + + for (auto& p: std::array<Point, 5> + {{{5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}}}) + pol2->addPoint(p); + + shapes.push_back(std::move(tri1)); + shapes.push_back(std::move(pol1)); + shapes.push_back(std::move(pol2)); + + for (auto& shape: shapes) + testShape(shape.get()); +} diff --git a/misc/examples/sidebyside.cpp b/misc/examples/sidebyside.cpp new file mode 100644 index 00000000..80c934a4 --- /dev/null +++ b/misc/examples/sidebyside.cpp @@ -0,0 +1,57 @@ +#include <iostream> +#include <map> +#include <string> +#include <stc/cstr.h> + +#define i_type IIMap +#define i_key int +#define i_val int +#include <stc/csmap.h> + +#define i_type SIMap +#define i_key_str +#define i_val int +#include <stc/cmap.h> + +int main() { + { + std::map<int, int> hist; + hist.emplace(12, 100).first->second += 1; + hist.emplace(13, 100).first->second += 1; + hist.emplace(12, 100).first->second += 1; + + for (auto i: hist) + std::cout << i.first << ", " << i.second << std::endl; + std::cout << std::endl; + } + + c_auto (IIMap, hist) + { + IIMap_insert(&hist, 12, 100).ref->second += 1; + IIMap_insert(&hist, 13, 100).ref->second += 1; + IIMap_insert(&hist, 12, 100).ref->second += 1; + + c_foreach (i, IIMap, hist) + printf("%d, %d\n", i.ref->first, i.ref->second); + puts(""); + } + // =================================================== + { + std::map<std::string, int> food = + {{"burger", 5}, {"pizza", 12}, {"steak", 15}}; + + for (auto i: food) + std::cout << i.first << ", " << i.second << std::endl; + std::cout << std::endl; + } + + c_auto (SIMap, food) + { + c_forlist (i, SIMap_raw, {{"burger", 5}, {"pizza", 12}, {"steak", 15}}) + SIMap_emplace(&food, c_PAIR(i.ref)); + + c_foreach (i, SIMap, food) + printf("%s, %d\n", cstr_str(&i.ref->first), i.ref->second); + puts(""); + } +} diff --git a/misc/examples/sorted_map.c b/misc/examples/sorted_map.c new file mode 100644 index 00000000..c4a05c76 --- /dev/null +++ b/misc/examples/sorted_map.c @@ -0,0 +1,64 @@ +// https://iq.opengenus.org/containers-cpp-stl/ + +#define i_key int +#define i_val int +#include <stc/csmap.h> +#include <stdio.h> + +int main() +{ + + // empty map containers + c_auto (csmap_int, gquiz1, gquiz2) + { + // insert elements in random order + csmap_int_insert(&gquiz1, 2, 30); + csmap_int_insert(&gquiz1, 4, 20); + csmap_int_insert(&gquiz1, 7, 10); + csmap_int_insert(&gquiz1, 5, 50); + csmap_int_insert(&gquiz1, 3, 60); + csmap_int_insert(&gquiz1, 1, 40); + csmap_int_insert(&gquiz1, 6, 50); + + // printing map gquiz1 + printf("\nThe map gquiz1 is :\n\tKEY\tELEMENT\n"); + c_foreach (itr, csmap_int, gquiz1) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // assigning the elements from gquiz1 to gquiz2 + c_foreach (i, csmap_int, gquiz1) + csmap_int_insert(&gquiz2, i.ref->first, i.ref->second); + + // print all elements of the map gquiz2 + printf("\nThe map gquiz2 is :\n\tKEY\tELEMENT\n"); + c_foreach (itr, csmap_int, gquiz2) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // remove all elements up to element with key=3 in gquiz2 + printf("\ngquiz2 after removal of elements less than key=3 :\n"); + printf("\tKEY\tELEMENT\n"); + csmap_int_erase_range(&gquiz2, csmap_int_begin(&gquiz2), + csmap_int_find(&gquiz2, 3)); + c_foreach (itr, csmap_int, gquiz2) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // remove all elements with key = 4 + int num = csmap_int_erase(&gquiz2, 4); + printf("\ngquiz2.erase(4) : %d removed\n", num); + printf("\tKEY\tELEMENT\n"); + c_foreach (itr, csmap_int, gquiz2) + printf("\t%d\t%d\n", itr.ref->first, itr.ref->second); + printf("\n"); + + // lower bound and upper bound for map gquiz1 key = 5 + printf("gquiz1.lower_bound(5) : "); + printf("\tKEY = %d\t", csmap_int_lower_bound(&gquiz1, 5).ref->first); + printf("\tELEMENT = %d\n", csmap_int_lower_bound(&gquiz1, 5).ref->second); + printf("gquiz1.upper_bound(5) : "); + printf("\tKEY = %d\t", csmap_int_lower_bound(&gquiz1, 5+1).ref->first); + printf("\tELEMENT = %d\n", csmap_int_lower_bound(&gquiz1, 5+1).ref->second); + } +} diff --git a/misc/examples/splitstr.c b/misc/examples/splitstr.c new file mode 100644 index 00000000..a3c12a3a --- /dev/null +++ b/misc/examples/splitstr.c @@ -0,0 +1,19 @@ +#include <stdio.h> +#define i_extern // cstr + utf8 functions +#include <stc/cregex.h> +#include <stc/csview.h> + +int main() +{ + puts("Split with c_fortoken (csview):"); + + c_fortoken (i, "Hello World C99!", " ") + printf("'%.*s'\n", c_ARGSV(i.token)); + + + puts("\nSplit with c_formatch (regex):"); + + c_with (cregex re = cregex_from("[^ ]+", CREG_DEFAULT), cregex_drop(&re)) + c_formatch (i, &re, " Hello World C99! ") + printf("'%.*s'\n", c_ARGSV(i.match[0])); +} diff --git a/misc/examples/sso_map.c b/misc/examples/sso_map.c new file mode 100644 index 00000000..cc5e16a1 --- /dev/null +++ b/misc/examples/sso_map.c @@ -0,0 +1,17 @@ +#include <stc/cstr.h> +#define i_key_str +#define i_val_str +#include <stc/cmap.h> + +int main() +{ + c_auto (cmap_str, m) { + cmap_str_emplace(&m, "Test short", "This is a short string."); + cmap_str_emplace(&m, "Test long ", "This is a longer string."); + + c_forpair (k, v, cmap_str, m) + printf("%s: '%s' Len=%" c_ZU ", Is long: %s\n", + cstr_str(_.k), cstr_str(_.v), cstr_size(_.v), + cstr_is_long(_.v)?"true":"false"); + } +} diff --git a/misc/examples/sso_substr.c b/misc/examples/sso_substr.c new file mode 100644 index 00000000..be372a8d --- /dev/null +++ b/misc/examples/sso_substr.c @@ -0,0 +1,20 @@ +#define STC_IMPLEMENT +#include <stc/cstr.h> +#include <stc/csview.h> + +int main () +{ + cstr str = cstr_lit("We think in generalities, but we live in details."); + csview sv1 = cstr_substr_ex(&str, 3, 5); // "think" + size_t pos = cstr_find(&str, "live"); // position of "live" + csview sv2 = cstr_substr_ex(&str, pos, 4); // "live" + csview sv3 = cstr_slice_ex(&str, -8, -1); // "details" + printf("%.*s, %.*s, %.*s\n", c_ARGSV(sv1), c_ARGSV(sv2), c_ARGSV(sv3)); + + cstr_assign(&str, "apples are green or red"); + cstr s2 = cstr_from_sv(cstr_substr_ex(&str, -3, 3)); // "red" + cstr s3 = cstr_from_sv(cstr_substr_ex(&str, 0, 6)); // "apples" + printf("%s %s: %d, %d\n", cstr_str(&s2), cstr_str(&s3), + cstr_is_long(&str), cstr_is_long(&s2)); + c_drop (cstr, &str, &s2, &s3); +} diff --git a/misc/examples/stack.c b/misc/examples/stack.c new file mode 100644 index 00000000..a6a4a492 --- /dev/null +++ b/misc/examples/stack.c @@ -0,0 +1,30 @@ + +#include <stdio.h> + +#define i_tag i +#define i_capacity 100 +#define i_val int +#include <stc/cstack.h> + +#define i_tag c +#define i_val char +#include <stc/cstack.h> + +int main() { + c_auto (cstack_i, stack) + c_auto (cstack_c, chars) + { + c_forrange (i, 101) + cstack_i_push(&stack, i*i); + + printf("%d\n", *cstack_i_top(&stack)); + + c_forrange (i, 90) + cstack_i_pop(&stack); + + c_foreach (i, cstack_i, stack) + printf(" %d", *i.ref); + puts(""); + printf("top: %d\n", *cstack_i_top(&stack)); + } +} diff --git a/misc/examples/sview_split.c b/misc/examples/sview_split.c new file mode 100644 index 00000000..d22fccd1 --- /dev/null +++ b/misc/examples/sview_split.c @@ -0,0 +1,20 @@ +#define STC_IMPLEMENT +#include <stc/cstr.h> +#include <stc/csview.h> + +int main() +{ + // No memory allocations or string length calculations! + const csview date = c_SV("2021/03/12"); + size_t pos = 0; + const csview year = csview_token(date, "/", &pos); + const csview month = csview_token(date, "/", &pos); + const csview day = csview_token(date, "/", &pos); + + printf("%.*s, %.*s, %.*s\n", c_ARGSV(year), c_ARGSV(month), c_ARGSV(day)); + + c_auto (cstr, y, m, d) { + y = cstr_from_sv(year), m = cstr_from_sv(month), d = cstr_from_sv(day); + printf("%s, %s, %s\n", cstr_str(&y), cstr_str(&m), cstr_str(&d)); + } +} diff --git a/misc/examples/unordered_set.c b/misc/examples/unordered_set.c new file mode 100644 index 00000000..a0b639da --- /dev/null +++ b/misc/examples/unordered_set.c @@ -0,0 +1,42 @@ +// https://iq.opengenus.org/containers-cpp-stl/ +// C program to demonstrate various function of stc cset +#include <stc/cstr.h> +#define i_key_str +#include <stc/cset.h> + +int main() +{ + // declaring set for storing string data-type + c_auto (cset_str, stringSet) + { + // inserting various string, same string will be stored + // once in set + cset_str_emplace(&stringSet, "code"); + cset_str_emplace(&stringSet, "in"); + cset_str_emplace(&stringSet, "C"); + cset_str_emplace(&stringSet, "is"); + cset_str_emplace(&stringSet, "fast"); + + const char* key = "slow"; + + // find returns end iterator if key is not found, + // else it returns iterator to that key + + if (cset_str_find(&stringSet, key).ref == cset_str_end(&stringSet).ref) + printf("\"%s\" not found\n", key); + else + printf("Found \"%s\"\n", key); + + key = "C"; + if (!cset_str_contains(&stringSet, key)) + printf("\"%s\" not found\n", key); + else + printf("Found \"%s\"\n", key); + + // now iterating over whole set and printing its + // content + printf("All elements :\n"); + c_foreach (itr, cset_str, stringSet) + printf("%s\n", cstr_str(itr.ref)); + } +} diff --git a/misc/examples/utf8replace_c.c b/misc/examples/utf8replace_c.c new file mode 100644 index 00000000..22a5c990 --- /dev/null +++ b/misc/examples/utf8replace_c.c @@ -0,0 +1,23 @@ +#define i_extern // add utf8 dependencies +#include <stc/cstr.h> +#include <stc/csview.h> + +int main() { + c_auto (cstr, hello, upper) { + hello = cstr_lit("hell😀 w😀rld"); + printf("%s\n", cstr_str(&hello)); + + /* replace second smiley at utf8 codepoint pos 7 */ + cstr_u8_replace(&hello, cstr_u8_to_pos(&hello, 7), 1, c_SV("🐨")); + printf("%s\n", cstr_str(&hello)); + + cstr_replace(&hello, "🐨", "ø", 1); + printf("%s\n", cstr_str(&hello)); + + upper = cstr_toupper_sv(cstr_sv(&hello)); + + c_foreach (c, cstr, hello) + printf("%.*s,", c_ARGSV(c.u8.chr)); + puts(""); + } +} diff --git a/misc/examples/utf8replace_rs.rs b/misc/examples/utf8replace_rs.rs new file mode 100644 index 00000000..717978aa --- /dev/null +++ b/misc/examples/utf8replace_rs.rs @@ -0,0 +1,19 @@ + +pub fn main() { + let mut hello = String::from("hell😀 world"); + println!("{}", hello); + + hello.replace_range( + hello + .char_indices() + .nth(4) + .map(|(pos, ch)| (pos..pos + ch.len_utf8())) + .unwrap(), + "🐨", + ); + println!("{}", hello); + + for c in hello.chars() { + print!("{},", c); + } +} diff --git a/misc/examples/vikings.c b/misc/examples/vikings.c new file mode 100644 index 00000000..26a74757 --- /dev/null +++ b/misc/examples/vikings.c @@ -0,0 +1,66 @@ +#include <stc/cstr.h> + +typedef struct Viking { + cstr name; + cstr country; +} Viking; + +void Viking_drop(Viking* vk) { + cstr_drop(&vk->name); + cstr_drop(&vk->country); +} + +// Define Viking lookup struct with hash, cmp, and convertion functions between Viking and RViking structs: + +typedef struct RViking { + const char* name; + const char* country; +} RViking; + +static inline int RViking_cmp(const RViking* rx, const RViking* ry) { + int c = strcmp(rx->name, ry->name); + return c ? c : strcmp(rx->country, ry->country); +} + +static inline Viking Viking_from(RViking raw) { // note: parameter is by value + return c_INIT(Viking){cstr_from(raw.name), cstr_from(raw.country)}; +} + +static inline RViking Viking_toraw(const Viking* vp) { + return c_INIT(RViking){cstr_str(&vp->name), cstr_str(&vp->country)}; +} + +// With this in place, we define the Viking => int hash map type: +#define i_type Vikings +#define i_keyclass Viking // key type +#define i_rawclass RViking // lookup type +#define i_keyfrom Viking_from +#define i_opt c_no_clone +#define i_hash(rp) cstrhash(rp->name) ^ cstrhash(rp->country) +#define i_val int // mapped type +#include <stc/cmap.h> +/* + i_keyclass implies these defines, unless they are already defined: + i_cmp => RViking_cmp + //i_hash => RViking_hash // already defined. + //i_keyclone => Viking_clone // not used, because of c_no_clone + i_keyto => Viking_toraw // because i_rawclass is defined + i_keydrop => Viking_drop +*/ + +int main() +{ + c_auto (Vikings, vikings) { + Vikings_emplace(&vikings, (RViking){"Einar", "Norway"}, 20); + Vikings_emplace(&vikings, (RViking){"Olaf", "Denmark"}, 24); + Vikings_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12); + Vikings_emplace(&vikings, (RViking){"Björn", "Sweden"}, 10); + + Vikings_value* v = Vikings_get_mut(&vikings, (RViking){"Einar", "Norway"}); + v->second += 3; // add 3 hp points to Einar + + c_forpair (vk, hp, Vikings, vikings) { + printf("%s of %s has %d hp\n", cstr_str(&_.vk->name), cstr_str(&_.vk->country), *_.hp); + } + } +} diff --git a/misc/examples/words.c b/misc/examples/words.c new file mode 100644 index 00000000..097447aa --- /dev/null +++ b/misc/examples/words.c @@ -0,0 +1,68 @@ +#include <math.h> +#include <stc/cstr.h> + +#define i_val_str +#include <stc/cvec.h> + +#define i_key_str +#define i_val int +#include <stc/cmap.h> + +int main1() +{ + c_auto (cvec_str, words) + c_auto (cmap_str, word_map) + { + c_forlist (i, const char*, { + "this", "sentence", "is", "not", "a", "sentence", + "this", "sentence", "is", "a", "hoax" + }) cvec_str_emplace_back(&words, *i.ref); + + c_foreach (w, cvec_str, words) { + cmap_str_emplace(&word_map, cstr_str(w.ref), 0).ref->second += 1; + } + + c_foreach (i, cmap_str, word_map) { + printf("%d occurrences of word '%s'\n", + i.ref->second, cstr_str(&i.ref->first)); + } + } + return 0; +} + +#ifdef __cplusplus +#include <string> +#include <iostream> +#include <vector> +#include <unordered_map> + +int main2() +{ + std::vector<std::string> words = { + "this", "sentence", "is", "not", "a", "sentence", + "this", "sentence", "is", "a", "hoax" + }; + + std::unordered_map<std::string, size_t> word_map; + for (const auto &w : words) { + word_map[w] += 1; + } + + for (const auto &pair : word_map) { + std::cout << pair.second + << " occurrences of word '" + << pair.first << "'\n"; + } + return 0; +} + +int main() { + main1(); + puts(""); + main2(); +} +#else +int main() { + main1(); +} +#endif |
