From a4bacdaf0feae20d417e53d8467ff332ac29413e Mon Sep 17 00:00:00 2001 From: tylo Date: Wed, 25 Aug 2021 12:04:46 +0200 Subject: BREAKING CHANGE: c_forvar_initdel() macro renamed to c_forauto(). Updated doc and improved csmap_erase.c example. --- docs/ccommon_api.md | 48 +++++++++++---- docs/csview_api.md | 2 +- examples/csmap_erase.c | 154 ++++++++++++++++++++++++------------------------- examples/priority.c | 2 +- include/stc/ccommon.h | 8 +-- 5 files changed, 121 insertions(+), 93 deletions(-) diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md index ddf3783c..d8125642 100644 --- a/docs/ccommon_api.md +++ b/docs/ccommon_api.md @@ -2,25 +2,53 @@ The following handy macros are safe to use, i.e. have no side-effects. -### c_fordefer, c_forscope, c_forvar, c_forvar_initdel +### c_fordefer, c_forscope, c_forvar, c_forauto General ***defer*** mechanics for resource acquisition. These macros allows to specify the release of the resource where the resource acquisition takes place. Makes it easier to verify that resources are released. -**Note**: These macros are one-time executed **for-loops**. Use ***only*** `continue` in order to break out -of a `c_for*`-block. ***Do not*** use `return`, `goto` or `break`, as they will prevent the `end`-statement to -be executed when leaving scope. This is not particular to the `c_for*()` macros, as one must always make sure -to unwind temporary allocated resources before a `return` in C. +**NB**: These macros are one-time executed **for-loops**. Use ***only*** `continue` in order to break out +of these four `c_for`-blocks. ***Do not*** use `return` or `goto` (or `break`) inside them, as they will +prevent the `end`-statement to be executed when leaving scope. This is not particular to the `c_for*()` +macros, as one must always make sure to unwind temporary allocated resources before a `return` in C. | Usage | Description | |:---------------------------------------|:--------------------------------------------------| -| `c_fordefer (end...)` | Defer execution of `end` to end of block | -| `c_forscope (start, end)` | Execute `start`. Defer `end` to end of block | | `c_forvar (Type var=init, end...)` | Declare `var`. Defer `end` to end of block | -| `c_forvar_initdel (Type, var...)` | `c_forvar (Type var=Type_init(), Type_del(&var))` | +| `c_forauto (Type, var...)` | `c_forvar (Type var=Type_init(), Type_del(&var))` | +| `c_forscope (start, end)` | Execute `start`. Defer `end` to end of block | +| `c_fordefer (end...)` | Defer execution of `end` to end of block | -For multiple variables, use either multiple **c_forvar** in sequence, or declare variable outside -scope and use **c_fordefer** or **c_forscope**. Also, **c_forvar_initdel** support up to 3 vars. +For multiple variables, use either multiple **c_forvar** in sequence, or declare variable outside +scope and use **c_forscope** or **c_fordefer**. Also, **c_forauto** support up to 3 vars. ```c +c_forvar (cstr s = cstr_lit("Hello"), cstr_del(&s)) +{ + cstr_append(&s, " world"); + printf("%s\n", s.str); +} + +c_forauto (cstr, s1, s2) +{ + cstr_append(&s1, "Hello"); + cstr_append(&s1, " world"); + + cstr_append(&s2, "Cool"); + cstr_append(&s2, " stuff"); + + printf("%s %s\n", s1.str, s2.str); +} + +using_cvec(i32, int32_t); +... +cvec_i32 vec; +c_forscope (vec = cvec_i32_init(), cvec_i32_del(&vec)) +{ + cvec_i32_push_back(&vec, 123); + cvec_i32_push_back(&vec, 321); + + c_foreach (i, cvec_i32, vec) printf(" %d", *i.ref); +} + cstr s1 = cstr_lit("Hello"), s2 = cstr_lit("world"); c_fordefer (cstr_del(&s1), cstr_del(&s2)) { diff --git a/docs/csview_api.md b/docs/csview_api.md index 2906acdc..70bc9b41 100644 --- a/docs/csview_api.md +++ b/docs/csview_api.md @@ -220,7 +220,7 @@ int main() csview suffix = csview_substr(text, -12, cstr_npos); // from pos -12 to end printf("%.*s\n", csview_ARG(suffix)); - c_forvar_initdel (cmap_si, map) + c_forauto (cmap_si, map) { cmap_si_emplace(&map, c_sv("hello"), 100); cmap_si_emplace(&map, c_sv("world"), 200); diff --git a/examples/csmap_erase.c b/examples/csmap_erase.c index 35afbe3a..6cebffb7 100644 --- a/examples/csmap_erase.c +++ b/examples/csmap_erase.c @@ -1,77 +1,77 @@ -// map_erase.c -// https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-16 -#include -#include -#include - -using_csmap_strval(my, int); - -void printmap(csmap_my map) -{ - c_foreach (e, csmap_my, map) - printf(" [%d, %s]", e.ref->first, e.ref->second.str); - printf("\nsize() == %zu\n\n", csmap_my_size(map)); -} - -int main() -{ - c_forvar (csmap_my m1 = csmap_my_init(), csmap_my_del(&m1)) - { - // Fill in some data to test with, one at a time - csmap_my_emplace(&m1, 1, "A"); - csmap_my_emplace(&m1, 2, "B"); - csmap_my_emplace(&m1, 3, "C"); - csmap_my_emplace(&m1, 4, "D"); - csmap_my_emplace(&m1, 5, "E"); - - puts("Starting data of map m1 is:"); - printmap(m1); - // The 1st member function removes an element at a given position - csmap_my_erase_at(&m1, csmap_my_fwd(csmap_my_begin(&m1), 1)); - puts("After the 2nd element is deleted, the map m1 is:"); - printmap(m1); - } - - c_forvar (csmap_my m2 = csmap_my_init(), csmap_my_del(&m2)) - { - // Fill in some data to test with, one at a time, using emplace - c_emplace(csmap_my, m2, { - {10, "Bob"}, - {11, "Rob"}, - {12, "Robert"}, - {13, "Bert"}, - {14, "Bobby"} - }); - - puts("Starting data of map m2 is:"); - printmap(m2); - csmap_my_iter_t it1 = csmap_my_fwd(csmap_my_begin(&m2), 1); - csmap_my_iter_t it2 = csmap_my_find(&m2, csmap_my_back(&m2)->first); - // The 2nd member function removes elements - // in the range [First, Last) - csmap_my_erase_range(&m2, it1, it2); - puts("After the middle elements are deleted, the map m2 is:"); - printmap(m2); - } - - c_forvar (csmap_my m3 = csmap_my_init(), csmap_my_del(&m3)) - { - // Fill in some data to test with, one at a time, using emplace - csmap_my_emplace(&m3, 1, "red"); - csmap_my_emplace(&m3, 2, "yellow"); - csmap_my_emplace(&m3, 3, "blue"); - csmap_my_emplace(&m3, 4, "green"); - csmap_my_emplace(&m3, 5, "orange"); - csmap_my_emplace(&m3, 5, "purple"); - csmap_my_emplace(&m3, 5, "pink"); - - puts("Starting data of map m3 is:"); - printmap(m3); - // The 3rd member function removes elements with a given Key - size_t count = csmap_my_erase(&m3, 2); - // The 3rd member function also returns the number of elements removed - printf("The number of elements removed from m3 is: %zu\n", count); - puts("After the element with a key of 2 is deleted, the map m3 is:"); - printmap(m3); - } -} \ No newline at end of file +// map_erase.c +// From C++ example: https://docs.microsoft.com/en-us/cpp/standard-library/map-class?view=msvc-160#example-16 +#include +#include +#include + +using_csmap_strval(my, int); + +void printmap(csmap_my map) +{ + c_foreach (e, csmap_my, map) + printf(" [%d, %s]", e.ref->first, e.ref->second.str); + printf("\nsize() == %zu\n\n", csmap_my_size(map)); +} + +int main() +{ + c_forauto (csmap_my, m1) + { + // Fill in some data to test with, one at a time + csmap_my_insert(&m1, 1, cstr_lit("A")); + csmap_my_insert(&m1, 2, cstr_lit("B")); + csmap_my_insert(&m1, 3, cstr_lit("C")); + csmap_my_insert(&m1, 4, cstr_lit("D")); + csmap_my_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 + csmap_my_erase_at(&m1, csmap_my_fwd(csmap_my_begin(&m1), 1)); + puts("After the 2nd element is deleted, the map m1 is:"); + printmap(m1); + } + + c_forauto (csmap_my, m2) + { + // Fill in some data to test with, one at a time, using c_emplace() + c_emplace(csmap_my, m2, { + {10, "Bob"}, + {11, "Rob"}, + {12, "Robert"}, + {13, "Bert"}, + {14, "Bobby"} + }); + + puts("Starting data of map m2 is:"); + printmap(m2); + csmap_my_iter_t it1 = csmap_my_fwd(csmap_my_begin(&m2), 1); + csmap_my_iter_t it2 = csmap_my_find(&m2, csmap_my_back(&m2)->first); + // The 2nd member function removes elements + // in the range [First, Last) + csmap_my_erase_range(&m2, it1, it2); + puts("After the middle elements are deleted, the map m2 is:"); + printmap(m2); + } + + c_forauto (csmap_my, m3) + { + // Fill in some data to test with, one at a time, using emplace + csmap_my_emplace(&m3, 1, "red"); + csmap_my_emplace(&m3, 2, "yellow"); + csmap_my_emplace(&m3, 3, "blue"); + csmap_my_emplace(&m3, 4, "green"); + csmap_my_emplace(&m3, 5, "orange"); + csmap_my_emplace(&m3, 6, "purple"); + csmap_my_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 = csmap_my_erase(&m3, 2); + // The 3rd member function also returns the number of elements removed + printf("The number of elements removed from m3 is: %zu\n", count); + puts("After the element with a key of 2 is deleted, the map m3 is:"); + printmap(m3); + } +} diff --git a/examples/priority.c b/examples/priority.c index ee64bf42..4824a294 100644 --- a/examples/priority.c +++ b/examples/priority.c @@ -13,7 +13,7 @@ int main() { size_t N = 10000000; stc64_t rng = stc64_init(time(NULL)); stc64_uniform_t dist = stc64_uniform_init(0, N * 10); - c_forvar (cpque_i heap = cpque_i_init(), cpque_i_del(&heap)) + c_forauto (cpque_i, heap) { // Push ten million random numbers to priority queue c_forrange (N) diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h index cdfb1e61..f79060a8 100644 --- a/include/stc/ccommon.h +++ b/include/stc/ccommon.h @@ -133,13 +133,13 @@ #define c_forscope(start, end) for (int _c_ii = (start, 0); !_c_ii; ++_c_ii, end) #define c_fordefer(...) for (int _c_ii = 0; !_c_ii; ++_c_ii, __VA_ARGS__) -#define c_forvar_initdel(...) c_MACRO_OVERLOAD(c_forvar_initdel, __VA_ARGS__) -#define c_forvar_initdel_2(CX, a) \ +#define c_forauto(...) c_MACRO_OVERLOAD(c_forauto, __VA_ARGS__) +#define c_forauto_2(CX, a) \ c_forvar(CX a = CX##_init(), CX##_del(&a)) -#define c_forvar_initdel_3(CX, a, b) \ +#define c_forauto_3(CX, a, b) \ c_forvar(c_EXPAND(CX a = CX##_init(), b = CX##_init()), \ CX##_del(&b), CX##_del(&a)) -#define c_forvar_initdel_4(CX, a, b, c) \ +#define c_forauto_4(CX, a, b, c) \ c_forvar(c_EXPAND(CX a = CX##_init(), b = CX##_init(), c = CX##_init()), \ CX##_del(&c), CX##_del(&b), CX##_del(&a)) -- cgit v1.2.3