From b0716d34433af4714f9a0b68278579fa1dd2b24e Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Wed, 20 Jan 2021 23:08:47 +0100 Subject: Improved README.md --- README.md | 87 ++++++++++++++++++++++++++++++++-------------------- docs/cvec_api.md | 39 +++++++++++++++++++++++ examples/phonebook.c | 72 ------------------------------------------- examples/share_ptr.c | 75 -------------------------------------------- examples/tmap.cpp | 53 -------------------------------- 5 files changed, 92 insertions(+), 234 deletions(-) delete mode 100644 examples/phonebook.c delete mode 100644 examples/share_ptr.c delete mode 100644 examples/tmap.cpp diff --git a/README.md b/README.md index 1918597b..6df8b7c7 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,9 @@ using_cvec(i, int); int main(void) { cvec_i vec = cvec_i_init(); - cvec_i_push_back(&vec, 1); - cvec_i_push_back(&vec, 2); + cvec_i_push_back(&vec, 10); + cvec_i_push_back(&vec, 20); + cvec_i_push_back(&vec, 30); c_foreach (i, cvec_i, vec) printf(" %d", *i.ref); @@ -48,47 +49,65 @@ int main(void) { cvec_i_del(&vec); } ``` -Container with elements of structs: +Here is five more... ```c -#include -#include - -typedef struct { - cstr name; // dynamic string - int id; -} User; - -int User_compare(const User* a, const User* b) { - int c = strcmp(a->name.str, b->name.str); - return c != 0 ? c : a->id - b->id; -} -void User_del(User* self) { - cstr_del(&self->name); -} -User User_clone(User user) { - user.name = cstr_clone(user.name); - return user; -} +#include +#include +#include +#include +#include +#include -// declare a memory managed, clonable vector of users: -using_cvec(u, User, User_compare, User_del, User_clone); +// declare your container types +using_cset(i, int); // unordered hash set +using_clist(i, int); // singly linked list +using_cdeq(i, int); // deque +using_cqueue(i, cdeq_i); // deque, using deque as adapter +using_csmap(i, int, int); // sorted map int main(void) { - cvec_u vec = cvec_u_init(); - cvec_u_push_back(&vec, (User) {cstr_from("admin"), 0}); - cvec_u_push_back(&vec, (User) {cstr_from("joe"), 1}); - - cvec_u vec2 = cvec_u_clone(vec); - c_foreach (i, cvec_u, vec2) - printf("%s: %d\n", i.ref->name.str, i.ref->id); - - c_del(cvec_u, &vec, &vec2); // cleanup + // define and initialize + c_init (cset_i, set, {10, 20, 30}); + c_init (clist_i, list, {10, 20, 30}); + c_init (cdeq_i, deq, {10, 20, 30}); + c_init (cqueue_i, que, {10, 20, 30}); + c_init (csmap_i, map, {{20, 2}, {10, 1}, {30, 3}}); + + // add one more element + cset_i_insert(&set, 40); + clist_i_push_front(&list, 5); + cdeq_i_push_front(&deq, 5); + cqueue_i_push(&que, 40); + csmap_i_emplace(&map, 40, 4); + + // print them + c_foreach (i, cset_i, set) printf(" %d", *i.ref); puts(""); + c_foreach (i, clist_i, list) printf(" %d", *i.ref); puts(""); + c_foreach (i, cdeq_i, deq) printf(" %d", *i.ref); puts(""); + c_foreach (i, cqueue_i, que) printf(" %d", *i.ref); puts(""); + c_foreach (i, csmap_i, map) printf(" (%d: %d)", i.ref->first, i.ref->second); + + // cleanup + cset_i_del(&set); + clist_i_del(&list); + cdeq_i_del(&deq); + cqueue_i_del(&que); + csmap_i_del(&map); } ``` +Outputs +``` + 10 20 30 40 + 5 10 20 30 + 5 10 20 30 + 10 20 30 40 + (10: 1) (20: 2) (30: 3) (40: 4) +``` + Motivation ---------- -The aim is to make a small **Standard Template Containers library for C**. It should +The aim was to make a small **Standard Template Containers library for C**. It should - be easy to use, have intuitive naming and consistency across the library. - be type safe. Have minimal usage of casting and void* pointers. - be highly efficient. Both in speed and memory usage. diff --git a/docs/cvec_api.md b/docs/cvec_api.md index 23083920..a94d10e1 100644 --- a/docs/cvec_api.md +++ b/docs/cvec_api.md @@ -173,3 +173,42 @@ item: Mary item: Jake item: 2 elements so far ``` +### Example 3 + +Container with elements of structs: +```c +#include +#include + +typedef struct { + cstr name; // dynamic string + int id; +} User; + +int User_compare(const User* a, const User* b) { + int c = strcmp(a->name.str, b->name.str); + return c != 0 ? c : a->id - b->id; +} +void User_del(User* self) { + cstr_del(&self->name); +} +User User_clone(User user) { + user.name = cstr_clone(user.name); + return user; +} + +// declare a memory managed, clonable vector of users: +using_cvec(u, User, User_compare, User_del, User_clone); + +int main(void) { + cvec_u vec = cvec_u_init(); + cvec_u_push_back(&vec, (User) {cstr_from("admin"), 0}); + cvec_u_push_back(&vec, (User) {cstr_from("joe"), 1}); + + cvec_u vec2 = cvec_u_clone(vec); + c_foreach (i, cvec_u, vec2) + printf("%s: %d\n", i.ref->name.str, i.ref->id); + + c_del(cvec_u, &vec, &vec2); // cleanup +} +``` diff --git a/examples/phonebook.c b/examples/phonebook.c deleted file mode 100644 index 91d01072..00000000 --- a/examples/phonebook.c +++ /dev/null @@ -1,72 +0,0 @@ -// 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 -#include -#include - -using_cmap_str(); - -void print_phone_book(cmap_str phone_book) -{ - c_foreach (i, cmap_str, phone_book) - printf("%s\t- %s\n", i.ref->first.str, i.ref->second.str); -} - -int main(int argc, char **argv) -{ - bool erased; - cmap_str phone_book = cmap_inits; - c_push_items(&phone_book, cmap_str, { - {"Lilia Friedman", "(892) 670-4739"}, - {"Tariq Beltran", "(489) 600-7575"}, - {"Laiba Juarez", "(303) 885-5692"}, - {"Elliott Mooney", "(945) 616-4482"}, - }); - - printf("Phone book:\n"); - print_phone_book(phone_book); - - c_try_emplace(&phone_book, cmap_str, "Zak Byers", cstr_from("(551) 396-1880")); - c_try_emplace(&phone_book, cmap_str, "Zak Byers", cstr_from("(551) 396-1990")); - - printf("\nPhone book after adding Zak Byers:\n"); - print_phone_book(phone_book); - - if (cmap_str_find(&phone_book, "Tariq Beltran") != NULL) - printf("\nTariq Beltran is in phone book\n"); - - erased = cmap_str_erase(&phone_book, "Tariq Beltran"); - erased = cmap_str_erase(&phone_book, "Elliott Mooney"); - - printf("\nPhone book after erasing Tariq and Elliott:\n"); - print_phone_book(phone_book); - - cmap_str_insert_or_assign(&phone_book, "Zak Byers", "(555) 396-188"); - - printf("\nPhone book after update phone of Zak Byers:\n"); - print_phone_book(phone_book); - - cmap_str_del(&phone_book); - puts("done"); -} \ No newline at end of file diff --git a/examples/share_ptr.c b/examples/share_ptr.c deleted file mode 100644 index 9387bd61..00000000 --- a/examples/share_ptr.c +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include -#include - -typedef struct { cstr_t name, last; } Person; - -Person* Person_make(Person* p, const char* name, const char* last) { - p->name = cstr_from(name), p->last = cstr_from(last); - return p; -} -void Person_del(Person* p) { - printf("del: %s\n", p->name.str); - c_del(cstr, &p->name, &p->last); -} -int Person_compare(const Person* p, const Person* q) { - int cmp = strcmp(p->name.str, q->name.str); - return cmp == 0 ? strcmp(p->last.str, q->last.str) : cmp; -} - -using_csptr(pe, Person, Person_compare, Person_del); -using_clist(pe, csptr_pe, csptr_pe_compare, csptr_pe_del, csptr_pe_clone); -using_cvec(pe, csptr_pe, csptr_pe_compare, csptr_pe_del, csptr_pe_clone); - -int main() { - clist_pe queue = clist_pe_init(); - cvec_pe vec = cvec_pe_init(); - - Person tmp = {cstr_from("Joe"), cstr_from("Jordan")}; - csptr_pe joe = csptr_pe_make(tmp); - clist_pe_push_back(&queue, csptr_pe_clone(joe)); - cvec_pe_push_back(&vec, csptr_pe_clone(joe)); - - puts("Push 10:"); - c_forrange (i, 10) { - csptr_pe p = csptr_pe_from(c_new(Person)); - p.get->name = cstr_from_fmt("Name %d", (i * 7) % 10); - p.get->last = cstr_from_fmt("Last %d", (i * 7) % 10); - clist_pe_push_back(&queue, p); - cvec_pe_push_back(&vec, csptr_pe_clone(p)); // Don't forget to share! - } - c_foreach (i, clist_pe, queue) - printf(" %s\n", i.ref->get->name.str); - - puts("Sort and pop 3:"); - clist_pe_sort(&queue); - cvec_pe_sort(&vec); - c_forrange (3) { - clist_pe_pop_front(&queue); - cvec_pe_pop_back(&vec); - } - - puts("Sorted queue:"); - c_foreach (i, clist_pe, queue) - printf(" %s\n", i.ref->get->name.str); - puts("Sorted vec:"); - c_foreach (i, cvec_pe, vec) - printf(" %s\n", i.ref->get->name.str); - - Person lost; Person_make(&lost, "Name 5", "Last 5"); - csptr_pe ptmp = {&lost, NULL}; // share pointer without counter - OK. - clist_pe_iter_t lit = clist_pe_find(&queue, ptmp); - Person_del(&lost); - if (lit.ref) printf("Found: %s\n", lit.ref->get->name.str); - - printf("use %ld\n", *joe.use_count); - csptr_pe_del(&joe); - - puts("Destroy queue:"); - clist_pe_del(&queue); - - puts("Destroy vec:"); - cvec_pe_del(&vec); -} \ No newline at end of file diff --git a/examples/tmap.cpp b/examples/tmap.cpp deleted file mode 100644 index 793ce6cc..00000000 --- a/examples/tmap.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include -#include -#include -#include - -using_csmap(i, int, size_t); -//using_csset_str(); - -#include - -int main(int argc, char **argv) -{ - std::map tmap; - csmap_i map = csmap_i_init(); - csmap_i_iter_t it; - time_t seed = time(NULL); - - size_t n = 2000000; - uint64_t mask = (1ull << 22) - 1; - - clock_t t1 = clock(); - stc64_srandom(seed); - for (size_t i = 0; i < n; ++i) { - uint64_t x = stc64_random() & mask; - tmap.emplace(x, i); - } - size_t s1 = tmap.size(); - stc64_srandom(seed); - for (size_t i = 0; i < n - 50; ++i) { - uint64_t x = stc64_random() & mask; - tmap.erase(x); - } - clock_t t2 = clock(); - - stc64_srandom(seed); - for (size_t i = 0; i < n; ++i) { - uint64_t x = stc64_random() & mask; - csmap_i_emplace(&map, x, i); - } - size_t s2 = csmap_i_size(map); - stc64_srandom(seed); - for (size_t i = 0; i < n - 50; ++i) { - uint64_t x = stc64_random() & mask; - csmap_i_erase(&map, x); - } - clock_t t3 = clock(); - - printf("%zu %zu\n", s1, s2); - printf("%zu %zu\n", tmap.size(), csmap_i_size(map)); - - printf("time: %f %f\n", ((float)t2-t1) / CLOCKS_PER_SEC, ((float)t3-t2) / CLOCKS_PER_SEC); -} -- cgit v1.2.3