From 6749cc21a2045d307c239d82891cb860687dfd2a Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Tue, 14 Dec 2021 19:50:10 +0100 Subject: Added and renamed some examples. --- examples/books.c | 60 ++++++++++++++++++++++++++++++++ examples/box.c | 61 ++++++++++++++++++++++++++++++++ examples/box2.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++ examples/hashmap.c | 48 ++++++++++++++++++++++++++ examples/ptr_elems.c | 62 --------------------------------- examples/rawptr_elements.c | 62 +++++++++++++++++++++++++++++++++ examples/sharedptr.c | 56 ------------------------------ examples/sptr_demo.c | 56 ++++++++++++++++++++++++++++++ examples/sptr_ex.c | 58 ------------------------------- examples/sptr_music.c | 58 +++++++++++++++++++++++++++++++ examples/sview_split.c | 17 +++++++++ 11 files changed, 448 insertions(+), 176 deletions(-) create mode 100644 examples/books.c create mode 100644 examples/box.c create mode 100644 examples/box2.c create mode 100644 examples/hashmap.c delete mode 100644 examples/ptr_elems.c create mode 100644 examples/rawptr_elements.c delete mode 100644 examples/sharedptr.c create mode 100644 examples/sptr_demo.c delete mode 100644 examples/sptr_ex.c create mode 100644 examples/sptr_music.c create mode 100644 examples/sview_split.c (limited to 'examples') diff --git a/examples/books.c b/examples/books.c new file mode 100644 index 00000000..f9340679 --- /dev/null +++ b/examples/books.c @@ -0,0 +1,60 @@ +// https://doc.rust-lang.org/std/collections/struct.HashMap.html + +#define i_key_str +#define i_val_str +#include + +// Type inference lets us omit an explicit type signature (which +// would be `HashMap` 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_new("The Adventures of Sherlock Holmes"), + cstr_new("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 %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; + if ((b = cmap_str_get(&book_reviews, to_find[i]))) + printf("%s: %s\n", b->first.str, b->second.str); + 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", cmap_str_at(&book_reviews, "Pride and Prejudice")->str); + + // Iterate over everything. + c_forpair (book, review, cmap_str, book_reviews) { + printf("%s: \"%s\"\n", _.book.str, _.review.str); + } + } +} \ No newline at end of file diff --git a/examples/box.c b/examples/box.c new file mode 100644 index 00000000..c7763bb8 --- /dev/null +++ b/examples/box.c @@ -0,0 +1,61 @@ +/* cbox: heap allocated boxed type */ +#include + +typedef struct { cstr name, last; } Person; + +Person Person_from(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 = strcmp(a->name.str, b->name.str); + return c ? c : strcmp(a->last.str, b->last.str); +} + +Person Person_clone(Person p) { + p.name = cstr_clone(p.name); + p.last = cstr_clone(p.last); + return p; +} +void Person_del(Person* p) { + printf("del: %s %s\n", p->name.str, p->last.str); + c_del(cstr, &p->name, &p->last); +} + +#define i_val Person +#define i_cmp Person_cmp +#define i_from Person_clone +#define i_del Person_del +#define i_tag prs +#include + +#define i_val_ref cbox_prs +#define i_tag prs +#include + + +int main() +{ + c_auto (cvec_prs, vec) + c_auto (cbox_prs, p, q) + { + p = cbox_prs_new(Person_from("Dave", "Cooper")); + + q = cbox_prs_clone(p); + cstr_assign(&q.get->name, "Dale"); + + printf("%s %s.\n", p.get->name.str, p.get->last.str); + printf("%s %s.\n", q.get->name.str, q.get->last.str); + + cvec_prs_push_back(&vec, cbox_prs_new(Person_from("Laura", "Palmer"))); + cvec_prs_push_back(&vec, cbox_prs_new(Person_from("Shelly", "Johnson"))); + + c_foreach (i, cvec_prs, vec) + printf("%s: %s\n", i.ref->get->name.str, i.ref->get->last.str); + + c_autovar (Person per = Person_from("Laura", "Palmer"), Person_del(&per)) { + const cbox_prs *v = cvec_prs_get(&vec, (cbox_prs){&per}); + if (v) printf("found: %s: %s\n", v->get->name.str, v->get->last.str); + } + } +} diff --git a/examples/box2.c b/examples/box2.c new file mode 100644 index 00000000..79304609 --- /dev/null +++ b/examples/box2.c @@ -0,0 +1,86 @@ +// https://doc.rust-lang.org/rust-by-example/std/box.html + +#include +#include +#include +#include + +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_compare +#include + +#define i_val cbox_Point +#define i_opt c_no_compare +#define i_tag BoxPoint +#include + +#define i_val Rectangle +#define i_opt c_no_compare +#include + +Point origin(void) { + return (Point){ .x=0.0, .y=0.0 }; +} + +cbox_Point boxed_origin(void) { + // Allocate this point on the heap, and return a pointer to it + return cbox_Point_new((Point){ .x=0.0, .y=0.0 }); +} + + +int main(void) { + // (all the type annotations are superfluous) + // Stack allocated variables + Point point = origin(); + Rectangle rectangle = (Rectangle){ + .top_left = origin(), + .bottom_right = (Point){ .x=3.0, .y=-4.0 } + }; + + // Heap allocated rectangle + c_auto (cbox_Rectangle, boxed_rectangle) + c_auto (cbox_Point, boxed_point) + c_auto (cbox_BoxPoint, box_in_a_box) + { + boxed_rectangle = cbox_Rectangle_new((Rectangle){ + .top_left = origin(), + .bottom_right = (Point){ .x=3.0, .y=-4.0 } + }); + + // The output of functions can be boxed + boxed_point = cbox_Point_new(origin()); + + // Double indirection + box_in_a_box = cbox_BoxPoint_new(boxed_origin()); + + printf("Point occupies %zu bytes on the stack\n", + sizeof(point)); + printf("Rectangle occupies %zu bytes on the stack\n", + sizeof(rectangle)); + + // box size == pointer size + printf("Boxed point occupies %zu bytes on the stack\n", + sizeof(boxed_point)); + printf("Boxed rectangle occupies %zu bytes on the stack\n", + sizeof(boxed_rectangle)); + printf("Boxed box occupies %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 %zu bytes on the stack\n", + sizeof(unboxed_point)); + } +} \ No newline at end of file diff --git a/examples/hashmap.c b/examples/hashmap.c new file mode 100644 index 00000000..c3e9afce --- /dev/null +++ b/examples/hashmap.c @@ -0,0 +1,48 @@ +// https://doc.rust-lang.org/rust-by-example/std/hash.html + +#define i_key_str +#define i_val_str +#include +#include + +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(v->second.str)); + else + printf("Don't have Daniel's number."); + + cmap_str_emplace(&contacts, "Daniel", "164-6743"); + + if ((v = cmap_str_get(&contacts, "Ashley"))) + printf("Calling Ashley: %s\n", call(v->second.str)); + 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", _.contact.str, call(_.number.str)); + } + puts(""); + } +} diff --git a/examples/ptr_elems.c b/examples/ptr_elems.c deleted file mode 100644 index c5416822..00000000 --- a/examples/ptr_elems.c +++ /dev/null @@ -1,62 +0,0 @@ -#include -#include - -struct { double x, y; } typedef Point; - -// Set of Point pointers: define all template parameters "in-line" -// Note it may be simpler to use a cbox for this. -#define i_key Point* -#define i_keydel(x) c_free(*(x)) -#define i_keyfrom(x) c_new(Point, *(x)) -#define i_hash(x, n) c_default_hash(*(x), sizeof *(x)) -#define i_equ(x, y) c_memcmp_equalto(*(x), *(y)) -#define i_tag pnt -#include - -// Map of int64 pointers: For fun, define valraw as int64_t for easy emplace call! -typedef int64_t inttype; -#define i_key_str -#define i_valraw inttype -#define i_val inttype* -#define i_valdel(x) c_free(*(x)) -#define i_valfrom(raw) c_new(inttype, raw) -#define i_valto(x) **(x) -#include - -int main() -{ - c_auto (cset_pnt, set, cpy) - { - printf("Set with pointer elements:\n"); - // c++: set.insert(new Point{1.2, 3.4}); - cset_pnt_insert(&set, c_new(Point, {1.2, 3.4})); - Point* q = *cset_pnt_insert(&set, c_new(Point, {6.1, 4.7})).ref; - cset_pnt_insert(&set, c_new(Point, {5.7, 2.3})); - - cpy = cset_pnt_clone(set); - cset_pnt_erase(&cpy, q); - - printf("set:"); - c_foreach (i, cset_pnt, set) - printf(" (%g %g)", i.ref[0]->x, i.ref[0]->y); - - printf("\ncpy:"); - c_foreach (i, cset_pnt, cpy) - printf(" (%g %g)", i.ref[0]->x, i.ref[0]->y); - puts(""); - } - - c_auto (cmap_str, map) - { - printf("\nMap with pointer elements:\n"); - cmap_str_insert(&map, cstr_new("testing"), c_new(inttype, 999)); - cmap_str_insert(&map, cstr_new("done"), c_new(inttype, 111)); - - // Emplace: implicit key, val construction using i_keyfrom/i_valfrom: - cmap_str_emplace(&map, "hello", 200); - cmap_str_emplace(&map, "goodbye", 400); - - c_forpair (name, number, cmap_str, map) - printf("%s: %zd\n", _.name.str, *_.number); - } -} diff --git a/examples/rawptr_elements.c b/examples/rawptr_elements.c new file mode 100644 index 00000000..c5416822 --- /dev/null +++ b/examples/rawptr_elements.c @@ -0,0 +1,62 @@ +#include +#include + +struct { double x, y; } typedef Point; + +// Set of Point pointers: define all template parameters "in-line" +// Note it may be simpler to use a cbox for this. +#define i_key Point* +#define i_keydel(x) c_free(*(x)) +#define i_keyfrom(x) c_new(Point, *(x)) +#define i_hash(x, n) c_default_hash(*(x), sizeof *(x)) +#define i_equ(x, y) c_memcmp_equalto(*(x), *(y)) +#define i_tag pnt +#include + +// Map of int64 pointers: For fun, define valraw as int64_t for easy emplace call! +typedef int64_t inttype; +#define i_key_str +#define i_valraw inttype +#define i_val inttype* +#define i_valdel(x) c_free(*(x)) +#define i_valfrom(raw) c_new(inttype, raw) +#define i_valto(x) **(x) +#include + +int main() +{ + c_auto (cset_pnt, set, cpy) + { + printf("Set with pointer elements:\n"); + // c++: set.insert(new Point{1.2, 3.4}); + cset_pnt_insert(&set, c_new(Point, {1.2, 3.4})); + Point* q = *cset_pnt_insert(&set, c_new(Point, {6.1, 4.7})).ref; + cset_pnt_insert(&set, c_new(Point, {5.7, 2.3})); + + cpy = cset_pnt_clone(set); + cset_pnt_erase(&cpy, q); + + printf("set:"); + c_foreach (i, cset_pnt, set) + printf(" (%g %g)", i.ref[0]->x, i.ref[0]->y); + + printf("\ncpy:"); + c_foreach (i, cset_pnt, cpy) + printf(" (%g %g)", i.ref[0]->x, i.ref[0]->y); + puts(""); + } + + c_auto (cmap_str, map) + { + printf("\nMap with pointer elements:\n"); + cmap_str_insert(&map, cstr_new("testing"), c_new(inttype, 999)); + cmap_str_insert(&map, cstr_new("done"), c_new(inttype, 111)); + + // Emplace: implicit key, val construction using i_keyfrom/i_valfrom: + cmap_str_emplace(&map, "hello", 200); + cmap_str_emplace(&map, "goodbye", 400); + + c_forpair (name, number, cmap_str, map) + printf("%s: %zd\n", _.name.str, *_.number); + } +} diff --git a/examples/sharedptr.c b/examples/sharedptr.c deleted file mode 100644 index c3da5287..00000000 --- a/examples/sharedptr.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include - -void int_del(int* x) { - printf("del: %d\n", *x); -} - -// csptr implements its own clone method using reference counting, -// so 'i_valfrom' need not be defined (will be ignored). - -#define i_type iref // set type name to be defined (instead of 'csptr_int') -#define i_val int -#define i_del int_del // optional, just to display the elements destroyed -#include // iref - -#define i_key_ref iref // note: use i_key_ref instead of i_key for csptr/cbox elements -#include // csset_iref (like: std::set>) - -#define i_val_ref iref // note: as above. -#include // cvec_iref (like: std::vector>) - -int main() -{ - c_auto (cvec_iref, vec) // declare and init vec, call cvec_iref_del() at scope exit - c_auto (csset_iref, set) // declare and init set, call csset_iref_del() at scope exit - { - const int years[] = {2021, 2012, 2022, 2015}; - c_forrange (i, c_arraylen(years)) - cvec_iref_push_back(&vec, iref_new(years[i])); - - printf("vec:"); - c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); - puts(""); - - // add odd numbers from vec to set - c_foreach (i, cvec_iref, vec) - if (*i.ref->get & 1) - csset_iref_emplace(&set, *i.ref); // copy shared pointer => increments counter. - - // erase the two last elements in vec - cvec_iref_pop_back(&vec); - cvec_iref_pop_back(&vec); - - printf("vec:"); - c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); - - printf("\nset:"); - c_foreach (i, csset_iref, set) printf(" %d", *i.ref->get); - - c_autovar (iref p = iref_clone(vec.data[0]), iref_del(&p)) { - printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count); - } - - puts("\nDone"); - } -} diff --git a/examples/sptr_demo.c b/examples/sptr_demo.c new file mode 100644 index 00000000..c3da5287 --- /dev/null +++ b/examples/sptr_demo.c @@ -0,0 +1,56 @@ +#include +#include + +void int_del(int* x) { + printf("del: %d\n", *x); +} + +// csptr implements its own clone method using reference counting, +// so 'i_valfrom' need not be defined (will be ignored). + +#define i_type iref // set type name to be defined (instead of 'csptr_int') +#define i_val int +#define i_del int_del // optional, just to display the elements destroyed +#include // iref + +#define i_key_ref iref // note: use i_key_ref instead of i_key for csptr/cbox elements +#include // csset_iref (like: std::set>) + +#define i_val_ref iref // note: as above. +#include // cvec_iref (like: std::vector>) + +int main() +{ + c_auto (cvec_iref, vec) // declare and init vec, call cvec_iref_del() at scope exit + c_auto (csset_iref, set) // declare and init set, call csset_iref_del() at scope exit + { + const int years[] = {2021, 2012, 2022, 2015}; + c_forrange (i, c_arraylen(years)) + cvec_iref_push_back(&vec, iref_new(years[i])); + + printf("vec:"); + c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); + puts(""); + + // add odd numbers from vec to set + c_foreach (i, cvec_iref, vec) + if (*i.ref->get & 1) + csset_iref_emplace(&set, *i.ref); // copy shared pointer => increments counter. + + // erase the two last elements in vec + cvec_iref_pop_back(&vec); + cvec_iref_pop_back(&vec); + + printf("vec:"); + c_foreach (i, cvec_iref, vec) printf(" %d", *i.ref->get); + + printf("\nset:"); + c_foreach (i, csset_iref, set) printf(" %d", *i.ref->get); + + c_autovar (iref p = iref_clone(vec.data[0]), iref_del(&p)) { + printf("\n%d is now owned by %ld objects\n", *p.get, *p.use_count); + } + + puts("\nDone"); + } +} diff --git a/examples/sptr_ex.c b/examples/sptr_ex.c deleted file mode 100644 index e8e08b5f..00000000 --- a/examples/sptr_ex.c +++ /dev/null @@ -1,58 +0,0 @@ -// 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 - -struct Song -{ - cstr artist; - cstr title; -} typedef Song; - -Song Song_from(const char* artist, const char* title) - { return (Song){cstr_from(artist), cstr_from(title)}; } - -void Song_del(Song* s) { - printf("del: %s\n", s->title.str); - c_del(cstr, &s->artist, &s->title); -} - -#define i_val Song -#define i_del Song_del -#define i_tag song -#define i_opt c_no_compare -#include // define csptr_song - -#define i_val_ref csptr_song -#define i_tag song -#include - -void example3() -{ - c_auto (cvec_song, v, v2) - { - c_apply(cvec_song, push_back, &v, { - csptr_song_new(Song_from("Bob Dylan", "The Times They Are A Changing")), - csptr_song_new(Song_from("Aretha Franklin", "Bridge Over Troubled Water")), - csptr_song_new(Song_from("Thalia", "Entre El Mar y Una Estrella")) - }); - - c_foreach (s, cvec_song, v) - if (!cstr_equals(s.ref->get->artist, "Bob Dylan")) - cvec_song_emplace_back(&v2, *s.ref); // note: calls csptr_song_clone() - - c_apply(cvec_song, push_back, &v2, { - csptr_song_new(Song_from("Michael Jackson", "Billie Jean")), - csptr_song_new(Song_from("Rihanna", "Stay")), - }); - - c_foreach (s, cvec_song, v2) - printf("%s - %s: refs %lu\n", s.ref->get->artist.str, s.ref->get->title.str, - *s.ref->use_count); - } -} - -int main() -{ - example3(); -} diff --git a/examples/sptr_music.c b/examples/sptr_music.c new file mode 100644 index 00000000..e8e08b5f --- /dev/null +++ b/examples/sptr_music.c @@ -0,0 +1,58 @@ +// 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 + +struct Song +{ + cstr artist; + cstr title; +} typedef Song; + +Song Song_from(const char* artist, const char* title) + { return (Song){cstr_from(artist), cstr_from(title)}; } + +void Song_del(Song* s) { + printf("del: %s\n", s->title.str); + c_del(cstr, &s->artist, &s->title); +} + +#define i_val Song +#define i_del Song_del +#define i_tag song +#define i_opt c_no_compare +#include // define csptr_song + +#define i_val_ref csptr_song +#define i_tag song +#include + +void example3() +{ + c_auto (cvec_song, v, v2) + { + c_apply(cvec_song, push_back, &v, { + csptr_song_new(Song_from("Bob Dylan", "The Times They Are A Changing")), + csptr_song_new(Song_from("Aretha Franklin", "Bridge Over Troubled Water")), + csptr_song_new(Song_from("Thalia", "Entre El Mar y Una Estrella")) + }); + + c_foreach (s, cvec_song, v) + if (!cstr_equals(s.ref->get->artist, "Bob Dylan")) + cvec_song_emplace_back(&v2, *s.ref); // note: calls csptr_song_clone() + + c_apply(cvec_song, push_back, &v2, { + csptr_song_new(Song_from("Michael Jackson", "Billie Jean")), + csptr_song_new(Song_from("Rihanna", "Stay")), + }); + + c_foreach (s, cvec_song, v2) + printf("%s - %s: refs %lu\n", s.ref->get->artist.str, s.ref->get->title.str, + *s.ref->use_count); + } +} + +int main() +{ + example3(); +} diff --git a/examples/sview_split.c b/examples/sview_split.c new file mode 100644 index 00000000..3a079583 --- /dev/null +++ b/examples/sview_split.c @@ -0,0 +1,17 @@ +#include +#define c_arg(a) a +int main() +{ + // No memory allocations or string length calculations! + const csview date = c_sv("2021/03/12"); + const csview year = csview_first_token(date, c_sv("/")); + const csview month = csview_next_token(date, c_sv("/"), year); + const csview day = csview_next_token(date, c_sv("/"), month); + + printf(c_svfmt ", " c_svfmt ", " c_svfmt "\n", c_svarg(year), c_svarg(month), c_svarg(day)); + + c_auto (cstr, y, m, d) { + y = cstr_from_v(year), m = cstr_from_v(month), d = cstr_from_v(day); + printf("%s, %s, %s\n", y.str, m.str, d.str); + } +} \ No newline at end of file -- cgit v1.2.3