summaryrefslogtreecommitdiffhomepage
path: root/docs/ccommon_api.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/ccommon_api.md')
-rw-r--r--docs/ccommon_api.md186
1 files changed, 93 insertions, 93 deletions
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 2c6db85f..a9961002 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -3,27 +3,27 @@
The following macros are recommended to use, and they safe/have no side-effects.
## Scope macros (RAII)
-### c_auto, c_autodrop, c_with, c_scope, c_defer
+### c_AUTO, c_AUTODROP, c_WITH, c_SCOPE, c_DEFER
General ***defer*** mechanics for resource acquisition. These macros allows you to specify the
freeing of the resources at the point where the acquisition takes place.
-The **checkauto** utility described below, ensures that the `c_auto*` macros are used correctly.
+The **checkauto** utility described below, ensures that the `c_AUTO*` macros are used correctly.
| Usage | Description |
|:---------------------------------------|:----------------------------------------------------------|
-| `c_with (Type var=init, drop)` | Declare `var`. Defer `drop...` to end of scope |
-| `c_with (Type var=init, pred, drop)` | Adds a predicate in order to exit early if init failed |
-| `c_auto (Type, var1,...,var4)` | `c_with (Type var1=Type_init(), Type_drop(&var1))` ... |
-| `c_autodrop (Type, var, init...)` | Like `c_with (Type var=init..., Type_drop(&var))` |
-| `c_scope (init, drop)` | Execute `init` and defer `drop` to end of scope |
-| `c_defer (drop...)` | Defer `drop...` to end of scope |
+| `c_WITH (Type var=init, drop)` | Declare `var`. Defer `drop...` to end of scope |
+| `c_WITH (Type var=init, pred, drop)` | Adds a predicate in order to exit early if init failed |
+| `c_AUTO (Type, var1,...,var4)` | `c_WITH (Type var1=Type_init(), Type_drop(&var1))` ... |
+| `c_AUTODROP (Type, var, init...)` | Like `c_WITH (Type var=init..., Type_drop(&var))` |
+| `c_SCOPE (init, drop)` | Execute `init` and defer `drop` to end of scope |
+| `c_DEFER (drop...)` | Defer `drop...` to end of scope |
| `continue` | Exit a block above without memory leaks |
-For multiple variables, use either multiple **c_with** in sequence, or declare variable outside
-scope and use **c_scope**. For convenience, **c_auto** support up to 4 variables.
+For multiple variables, use either multiple **c_WITH** in sequence, or declare variable outside
+scope and use **c_SCOPE**. For convenience, **c_AUTO** support up to 4 variables.
```c
-// `c_with` is similar to python `with`: it declares and can drop a variable after going out of scope.
-c_with (uint8_t* buf = malloc(BUF_SIZE), free(buf))
-c_with (FILE* fp = fopen(fname, "rb"), fclose(fp))
+// `c_WITH` is similar to python `with`: it declares and can drop a variable after going out of scope.
+c_WITH (uint8_t* buf = malloc(BUF_SIZE), free(buf))
+c_WITH (FILE* fp = fopen(fname, "rb"), fclose(fp))
{
int n = 0;
if (fp && buf) {
@@ -32,14 +32,14 @@ c_with (FILE* fp = fopen(fname, "rb"), fclose(fp))
}
}
-c_with (cstr str = cstr_lit("Hello"), cstr_drop(&str))
+c_WITH (cstr str = cstr_lit("Hello"), cstr_drop(&str))
{
cstr_append(&str, " world");
printf("%s\n", cstr_str(&str));
}
-// `c_auto` automatically initialize and destruct up to 4 variables, like `c_with`.
-c_auto (cstr, s1, s2)
+// `c_AUTO` automatically initialize and destruct up to 4 variables, like `c_WITH`.
+c_AUTO (cstr, s1, s2)
{
cstr_append(&s1, "Hello");
cstr_append(&s1, " world");
@@ -50,22 +50,22 @@ c_auto (cstr, s1, s2)
printf("%s %s\n", cstr_str(&s1), cstr_str(&s2));
}
-c_autodrop (cstr, str, cstr_lit("Hello"))
+c_AUTODROP (cstr, str, cstr_lit("Hello"))
{
cstr_append(&str, " world");
printf("%s\n", cstr_str(&str));
}
-// `c_scope` is like `c_with` but works with an already declared variable.
+// `c_SCOPE` is like `c_WITH` but works with an already declared variable.
static pthread_mutex_t mut;
-c_scope (pthread_mutex_lock(&mut), pthread_mutex_unlock(&mut))
+c_SCOPE (pthread_mutex_lock(&mut), pthread_mutex_unlock(&mut))
{
/* Do syncronized work. */
}
-// `c_defer` executes the expressions when leaving scope.
+// `c_DEFER` executes the expressions when leaving scope.
cstr s1 = cstr_lit("Hello"), s2 = cstr_lit("world");
-c_defer (cstr_drop(&s1), cstr_drop(&s2))
+c_DEFER (cstr_drop(&s1), cstr_drop(&s2))
{
printf("%s %s\n", cstr_str(&s1), cstr_str(&s2));
}
@@ -83,8 +83,8 @@ cvec_str readFile(const char* name)
{
cvec_str vec = cvec_str_init(); // returned
- c_with (FILE* fp = fopen(name, "r"), fclose(fp))
- c_with (cstr line = cstr_NULL, cstr_drop(&line))
+ c_WITH (FILE* fp = fopen(name, "r"), fclose(fp))
+ c_WITH (cstr line = cstr_NULL, cstr_drop(&line))
while (cstr_getline(&line, fp))
cvec_str_emplace_back(&vec, cstr_str(&line));
return vec;
@@ -92,30 +92,30 @@ cvec_str readFile(const char* name)
int main()
{
- c_with (cvec_str x = readFile(__FILE__), cvec_str_drop(&x))
- c_foreach (i, cvec_str, x)
+ c_WITH (cvec_str x = readFile(__FILE__), cvec_str_drop(&x))
+ c_FOREACH (i, cvec_str, x)
printf("%s\n", cstr_str(i.ref));
}
```
### The **checkauto** utility program (for RAII)
-The **checkauto** program will check the source code for any misuses of the `c_auto*` macros which
-may lead to resource leakages. The `c_auto*`- macros are implemented as one-time executed **for-loops**,
+The **checkauto** program will check the source code for any misuses of the `c_AUTO*` macros which
+may lead to resource leakages. The `c_AUTO*`- macros are implemented as one-time executed **for-loops**,
so any `return` or `break` appearing within such a block will lead to resource leaks, as it will disable
the cleanup/drop method to be called. A `break` may originally be intended to break a loop or switch
-outside the `c_auto` scope.
+outside the `c_AUTO` scope.
-NOTE: One must always make sure to unwind temporary allocated resources before a `return` in C. However, by using `c_auto*`-macros,
+NOTE: One must always make sure to unwind temporary allocated resources before a `return` in C. However, by using `c_AUTO*`-macros,
- it is much easier to automatically detect misplaced return/break between resource acquisition and destruction.
- it prevents forgetting to call the destructor at the end.
The **checkauto** utility will report any misusages. The following example shows how to correctly break/return
-from a `c_auto` scope:
+from a `c_AUTO` scope:
```c
int flag = 0;
for (int i = 0; i<n; ++i) {
- c_auto (cstr, text)
- c_auto (List, list)
+ c_AUTO (cstr, text)
+ c_AUTO (List, list)
{
for (int j = 0; j<m; ++j) {
List_push_back(&list, i*j);
@@ -124,23 +124,23 @@ from a `c_auto` scope:
}
// WRONG:
if (cond2())
- break; // checkauto ERROR! break inside c_auto.
+ break; // checkauto ERROR! break inside c_AUTO.
if (cond3())
- return -1; // checkauto ERROR! return inside c_auto
+ return -1; // checkauto ERROR! return inside c_AUTO
// CORRECT:
if (cond2()) {
flag = 1; // flag to break outer for-loop
- continue; // cleanup and leave c_auto block
+ continue; // cleanup and leave c_AUTO block
}
if (cond3()) {
flag = -1; // return -1
- continue; // cleanup and leave c_auto block
+ continue; // cleanup and leave c_AUTO block
}
...
}
- // do the return/break outside of c_auto
+ // do the return/break outside of c_AUTO
if (flag < 0) return flag;
else if (flag > 0) break;
...
@@ -148,33 +148,33 @@ from a `c_auto` scope:
```
## Loop abstraction macros
-### c_forlist
+### c_FORLIST
Iterate compound literal array elements. Additional to `i.ref`, you can access `i.data`, `i.size`, and `i.index` of the input list/element.
```c
// apply multiple push_backs
-c_forlist (i, int, {1, 2, 3})
+c_FORLIST (i, int, {1, 2, 3})
cvec_i_push_back(&vec, *i.ref);
// insert in existing map
-c_forlist (i, cmap_ii_raw, { {4, 5}, {6, 7} })
+c_FORLIST (i, cmap_ii_raw, { {4, 5}, {6, 7} })
cmap_ii_insert(&map, i.ref->first, i.ref->second);
// string literals pushed to a stack of cstr:
-c_forlist (i, const char*, {"Hello", "crazy", "world"})
+c_FORLIST (i, const char*, {"Hello", "crazy", "world"})
cstack_str_emplace(&stk, *i.ref);
// reverse the list:
-c_forlist (i, int, {1, 2, 3})
+c_FORLIST (i, int, {1, 2, 3})
cvec_i_push_back(&vec, i.data[i.size - 1 - i.index]);
```
-### c_foreach, c_forpair
+### c_FOREACH, c_FORPAIR
| Usage | Description |
|:-----------------------------------------|:--------------------------------|
-| `c_foreach (it, ctype, container)` | Iteratate all elements |
-| `c_foreach (it, ctype, it1, it2)` | Iterate the range [it1, it2) |
-| `c_forpair (key, val, ctype, container)` | Iterate with structured binding |
+| `c_FOREACH (it, ctype, container)` | Iteratate all elements |
+| `c_FOREACH (it, ctype, it1, it2)` | Iterate the range [it1, it2) |
+| `c_FORPAIR (key, val, ctype, container)` | Iterate with structured binding |
```c
#define i_key int
@@ -182,59 +182,59 @@ c_forlist (i, int, {1, 2, 3})
#define i_tag ii
#include <stc/csmap.h>
...
-c_forlist (i, csmap_ii_raw, { {23,1}, {3,2}, {7,3}, {5,4}, {12,5} })
+c_FORLIST (i, csmap_ii_raw, { {23,1}, {3,2}, {7,3}, {5,4}, {12,5} })
csmap_ii_insert(&map, i.ref->first, i.ref->second);
-c_foreach (i, csmap_ii, map)
+c_FOREACH (i, csmap_ii, map)
printf(" %d", i.ref->first);
// 3 5 7 12 23
csmap_ii_iter it = csmap_ii_find(&map, 7);
-c_foreach (i, csmap_ii, it, csmap_ii_end(&map))
+c_FOREACH (i, csmap_ii, it, csmap_ii_end(&map))
printf(" %d", i.ref->first);
// 7 12 23
-c_forpair (id, count, csmap_ii, map)
+c_FORPAIR (id, count, csmap_ii, map)
printf(" (%d %d)", *_.id, *_.count);
// (3 2) (5 4) (7 3) (12 5) (23 1)
```
-### c_forrange
+### c_FORRANGE
Abstraction for iterating sequence of numbers. Like python's **for** *i* **in** *range()* loop.
| Usage | Python equivalent |
|:--------------------------------------------|:-------------------------------------|
-| `c_forrange (stop)` | `for _ in range(stop):` |
-| `c_forrange (i, stop) // i type = long long` | `for i in range(stop):` |
-| `c_forrange (i, start, stop)` | `for i in range(start, stop):` |
-| `c_forrange (i, start, stop, step)` | `for i in range(start, stop, step):` |
+| `c_FORRANGE (stop)` | `for _ in range(stop):` |
+| `c_FORRANGE (i, stop) // i type = long long` | `for i in range(stop):` |
+| `c_FORRANGE (i, start, stop)` | `for i in range(start, stop):` |
+| `c_FORRANGE (i, start, stop, step)` | `for i in range(start, stop, step):` |
```c
-c_forrange (5) printf("x");
+c_FORRANGE (5) printf("x");
// xxxxx
-c_forrange (i, 5) printf(" %lld", i);
+c_FORRANGE (i, 5) printf(" %lld", i);
// 0 1 2 3 4
-c_forrange (i, -3, 3) printf(" %lld", i);
+c_FORRANGE (i, -3, 3) printf(" %lld", i);
// -3 -2 -1 0 1 2
-c_forrange (i, 30, 0, -5) printf(" %lld", i);
+c_FORRANGE (i, 30, 0, -5) printf(" %lld", i);
// 30 25 20 15 10 5
```
-### c_forwhile, c_forfilter
+### c_FORWHILE, c_FORFILTER
Iterate containers with stop-criteria and chained range filtering.
| Usage | Description |
|:----------------------------------------------------|:---------------------------------------|
-| `c_forwhile (it, ctype, start, pred)` | Iterate until pred is false |
-| `c_forfilter (it, ctype, container, filter)` | Filter out items in chain with && |
-| `c_forfilter (it, ctype, container, filter, pred)` | Filter and iterate until pred is false |
+| `c_FORWHILE (it, ctype, start, pred)` | Iterate until pred is false |
+| `c_FORFILTER (it, ctype, container, filter)` | Filter out items in chain with && |
+| `c_FORFILTER (it, ctype, container, filter, pred)` | Filter and iterate until pred is false |
| Built-in filter | Description |
|:----------------------------------|:-------------------------------------|
-| `c_flt_skip(it, numItems)` | Skip numItems |
-| `c_flt_take(it, numItems)` | Take numItems |
-| `c_flt_skipwhile(it, predicate)` | Skip items until predicate is false |
-| `c_flt_takewhile(it, predicate)` | Take items until predicate is false |
+| `c_FLT_SKIP(it, numItems)` | Skip numItems |
+| `c_FLT_TAKE(it, numItems)` | Take numItems |
+| `c_FLT_SKIPWHILE(it, predicate)` | Skip items until predicate is false |
+| `c_FLT_TAKEWHILE(it, predicate)` | Take items until predicate is false |
`it.index` holds the index of the source item, and `it.count` the current number of items taken.
```c
@@ -250,14 +250,14 @@ bool isPrime(int i) {
#define isOdd(i) ((i) & 1)
int main() {
- c_auto (IVec, vec) {
- c_forrange (i, 1000) IVec_push(&vec, 1000000 + i);
+ c_AUTO (IVec, vec) {
+ c_FORRANGE (i, 1000) IVec_push(&vec, 1000000 + i);
- c_forfilter (i, IVec, vec,
+ c_FORFILTER (i, IVec, vec,
isOdd(*i.ref)
- && c_flt_skip(i, 100) // built-in
+ && c_FLT_SKIP(i, 100) // built-in
&& isPrime(*i.ref)
- , c_flt_take(i, 10)) { // breaks loop on false.
+ , c_FLT_TAKE(i, 10)) { // breaks loop on false.
printf(" %d", *i.ref);
}
puts("");
@@ -265,7 +265,7 @@ int main() {
}
// Out: 1000211 1000213 1000231 1000249 1000253 1000273 1000289 1000291 1000303 1000313
```
-Note that `c_flt_take()` is given as an optional argument, which makes the loop stop when it becomes false (for efficiency). Chaining it after `isPrime()` instead will give same result, but the full input is processed.
+Note that `c_FLT_TAKE()` is given as an optional argument, which makes the loop stop when it becomes false (for efficiency). Chaining it after `isPrime()` instead will give same result, but the full input is processed.
### crange
**crange** is a number sequence generator type. The **crange_value** type is `long long`. Below, *start*, *stop*, *step* are type *crange_value*:
@@ -281,57 +281,57 @@ void crange_next(crange_iter* it);
// 1. All primes less than 32:
crange r1 = crange_make(3, 32, 2);
printf("2"); // first prime
-c_forfilter (i, crange, r1
+c_FORFILTER (i, crange, r1
, isPrime(*i.ref))
printf(" %lld", *i.ref);
// 2 3 5 7 11 13 17 19 23 29 31
// 2. The 11 first primes:
printf("2");
-c_forfilter (i, crange, crange_literal(3, crange_MAX, 2)
+c_FORFILTER (i, crange, crange_literal(3, crange_MAX, 2)
, isPrime(*i.ref)
- , c_flt_take(10))
+ , c_FLT_TAKE(10))
printf(" %lld", *i.ref);
// 2 3 5 7 11 13 17 19 23 29 31
```
-### c_find_if, c_find_in, c_erase_if
+### c_FIND_IF, c_find_in, c_ERASE_IF
Find or erase linearily in containers using a predicate
```c
// Search vec for first value > 2:
cvec_i_iter i;
-c_find_if(i, cvec_i, vec, *i.ref > 2);
+c_FIND_IF(i, cvec_i, vec, *i.ref > 2);
if (i.ref) printf("%d\n", *i.ref);
// Search map for a string containing "hello" and erase it:
cmap_str_iter it, it1 = ..., it2 = ...;
-c_find_if(it, csmap_str, it1, it2, cstr_contains(it.ref, "hello"));
+c_FIND_IF(it, csmap_str, it1, it2, cstr_contains(it.ref, "hello"));
if (it.ref) cmap_str_erase_at(&map, it);
// Erase all strings containing "hello":
// Note 1: iter i need not be declared.
// Note 2: variables index and count can be accessed in predicate.
-c_erase_if(i, csmap_str, map, cstr_contains(i.ref, "hello"));
+c_ERASE_IF(i, csmap_str, map, cstr_contains(i.ref, "hello"));
```
-### c_new, c_alloc, c_alloc_n, c_drop
+### c_NEW, c_ALLOC, c_ALLOC_N, c_DROP
| Usage | Meaning |
|:-------------------------------|:----------------------------------------|
-| `c_new (type, value)` | Move value to a new object on the heap |
-| `c_alloc (type)` | `(type *) c_malloc(sizeof(type))` |
-| `c_alloc_n (type, N)` | `(type *) c_malloc((N)*sizeof(type))` |
-| `c_drop (ctype, &c1, ..., &cN)` | `ctype_drop(&c1); ... ctype_drop(&cN)` |
+| `c_NEW (type, value)` | Move value to a new object on the heap |
+| `c_ALLOC (type)` | `(type *) c_MALLOC(sizeof(type))` |
+| `c_ALLOC_N (type, N)` | `(type *) c_MALLOC((N)*sizeof(type))` |
+| `c_DROP (ctype, &c1, ..., &cN)` | `ctype_drop(&c1); ... ctype_drop(&cN)` |
```c
struct Pnt { double x, y, z; };
-struct Pnt *pnt = c_new (struct Pnt, {1.2, 3.4, 5.6});
-c_free(pnt);
+struct Pnt *pnt = c_NEW (struct Pnt, {1.2, 3.4, 5.6});
+c_FREE(pnt);
-int* array = c_alloc_n (int, 100);
-c_free(array);
+int* array = c_ALLOC_N (int, 100);
+c_FREE(array);
cstr a = cstr_lit("Hello"), b = cstr_lit("World");
-c_drop(cstr, &a, &b);
+c_DROP(cstr, &a, &b);
```
### General predefined template parameter functions
@@ -347,9 +347,9 @@ bool crawstr_eq(const crawstr* x, const crawstr* y);
uint64_t crawstr_hash(const crawstr* x);
```
-### c_malloc, c_calloc, c_realloc, c_free
+### c_MALLOC, c_CALLOC, c_REALLOC, c_FREE
Memory allocator for the entire library. Macros can be overloaded by the user.
-### c_swap, c_arraylen
+### c_swap, c_ARRAYLEN
- **c_swap(type, x, y)**: Simple macro for swapping internals of two objects.
-- **c_arraylen(array)**: Return number of elements in an array, e.g. `int array[] = {1, 2, 3, 4};`
+- **c_ARRAYLEN(array)**: Return number of elements in an array, e.g. `int array[] = {1, 2, 3, 4};`