summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--docs/cbox_api.md2
-rw-r--r--docs/ccommon_api.md119
-rw-r--r--include/stc/carc.h12
-rw-r--r--include/stc/cbox.h14
-rw-r--r--include/stc/ccommon.h18
-rw-r--r--include/stc/cdeq.h1
-rw-r--r--include/stc/cstack.h3
-rw-r--r--include/stc/cvec.h4
-rw-r--r--misc/examples/box2.c74
-rw-r--r--misc/examples/list.c8
10 files changed, 141 insertions, 114 deletions
diff --git a/docs/cbox_api.md b/docs/cbox_api.md
index eff0fbc1..8b03d004 100644
--- a/docs/cbox_api.md
+++ b/docs/cbox_api.md
@@ -42,7 +42,7 @@ cbox_X cbox_X_make(i_val val); // create a cbox f
cbox_X cbox_X_clone(cbox_X other); // return deep copied clone
cbox_X cbox_X_move(cbox_X* self); // transfer ownership to receiving cbox returned. self becomes NULL.
void cbox_X_take(cbox_X* self, cbox_X unowned); // take ownership of unowned box object.
-void cbox_X_assign(cbox_X* self, cbox_X* dying); // transfer ownership from dying to self; dying becomes NULL.
+void cbox_X_assign(cbox_X* self, cbox_X* moved); // transfer ownership from moved to self; moved becomes NULL.
void cbox_X_drop(cbox_X* self); // destruct the contained object and free its heap memory.
void cbox_X_reset(cbox_X* self);
diff --git a/docs/ccommon_api.md b/docs/ccommon_api.md
index 60167c06..034e52f5 100644
--- a/docs/ccommon_api.md
+++ b/docs/ccommon_api.md
@@ -94,26 +94,6 @@ int main()
```
## Loop abstraction macros
-### 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})
- cvec_i_push_back(&vec, *i.ref);
-
-// insert in existing map
-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"})
- cstack_str_emplace(&stk, *i.ref);
-
-// reverse the list:
-c_forlist (i, int, {1, 2, 3})
- cvec_i_push_back(&vec, i.data[i.size - 1 - i.index]);
-```
-
### c_foreach, c_forpair
| Usage | Description |
@@ -150,10 +130,10 @@ c_forpair (id, count, csmap_ii, map)
```
### c_forrange
-Abstraction for iterating sequence of numbers. Like python's **for** *i* **in** *range()* loop.
+Abstraction for iterating sequence of integers. Like python's **for** *i* **in** *range()* loop.
-| Usage | Python equivalent |
-|:--------------------------------------------|:-------------------------------------|
+| 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):` |
@@ -170,6 +150,26 @@ c_forrange (i, 30, 0, -5) printf(" %lld", i);
// 30 25 20 15 10 5
```
+### 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})
+ cvec_i_push_back(&vec, *i.ref);
+
+// insert in existing map
+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"})
+ cstack_str_emplace(&stk, *i.ref);
+
+// reverse the list:
+c_forlist (i, int, {1, 2, 3})
+ cvec_i_push_back(&vec, i.data[i.size - 1 - i.index]);
+```
+
### c_forfilter
Iterate containers with stop-criteria and chained range filtering.
@@ -218,33 +218,7 @@ int main() {
Note that `c_flt_take()` is given as an optional argument, which breaks the loop on false.
With `&&` instead of the comma it will give same result, but the full input is processed first.
-### c_make, c_new, c_delete
-
-- **c_make**: Make any container from an initializer list. Example:
-```c
-#define i_val_str // cstr value type
-#include <stc/cset.h>
-
-#define i_key int
-#define i_val int
-#include <stc/cmap.h>
-...
-// Initializes with const char*, internally converted to cstr!
-cset_str myset = c_make(cset_str, {"This", "is", "the", "story"});
-
-int x = 7, y = 8;
-cmap_int mymap = c_make(cmap_int, { {1, 2}, {3, 4}, {5, 6}, {x, y} });
-```
-
-- **c_new(Type)**: Allocate *and init* a new object on the heap
-- **c_delete(Type, ptr)**: Drop *and free* an object allocated on the heap
-```c
-#include <stc/cstr.h>
-
-cstr *stringptr = c_new(cstr, cstr_from("Hello"));
-printf("%s\n", cstr_str(stringptr));
-c_delete(cstr, stringptr);
-```
+## Generators
### crange
A number sequence generator type, similar to [boost::irange](https://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/ranges/irange.html). The **crange_value** type is `long long`. Below *start*, *stop*, and *step* are of type *crange_value*:
@@ -274,24 +248,61 @@ c_forfilter (i, crange, crange_obj(3, INT64_MAX, 2)
printf(" %lld", *i.ref);
// 2 3 5 7 11 13 17 19 23 29 31
```
-### c_find_if, c_erase_if, c_swap, c_drop
+## Algorithms
+
+### c_make, c_new, c_delete
+
+- *c_make(C, {...})*: Make any container from an initializer list. Example:
+```c
+#define i_val_str // cstr value type
+#include <stc/cset.h>
+
+#define i_key int
+#define i_val int
+#include <stc/cmap.h>
+...
+// Initializes with const char*, internally converted to cstr!
+cset_str myset = c_make(cset_str, {"This", "is", "the", "story"});
+
+int x = 7, y = 8;
+cmap_int mymap = c_make(cmap_int, { {1, 2}, {3, 4}, {5, 6}, {x, y} });
+```
+
+- ***c_new(Type)***: Allocate *and init* a new object on the heap
+- ***c_delete(Type, ptr)***: Drop *and free* an object allocated on the heap
+```c
+#include <stc/cstr.h>
+
+cstr *stringptr = c_new(cstr, cstr_from("Hello"));
+printf("%s\n", cstr_str(stringptr));
+c_delete(cstr, stringptr);
+```
+
+### c_find_if, c_erase_if, c_eraseremove_if
Find or erase linearily in containers using a predicate
+- For *c_find_if (iter, C, c, pred)*, ***iter*** must be declared outside/prior to call.
+- Use *c_erase_if (iter, C, c, pred)* with **clist**, **cmap**, **cset**, **csmap**, and **csset**.
+- Use *c_eraseremove_if (iter, C, c, pred)* with **cstack**, **cvec**, **cdeq**, and **cqueue**.
```c
// Search vec for first value > 2:
cvec_i_iter i;
c_find_if(i, cvec_i, vec, *i.ref > 2);
if (i.ref) printf("%d\n", *i.ref);
+// Erase all values > 2 in vec:
+c_eraseremove_if(i, cvec_i, vec, *i.ref > 2);
+
// 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"));
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.
+// Erase all strings containing "hello" in a sorted map:
c_erase_if(i, csmap_str, map, cstr_contains(i.ref, "hello"));
+```
+### c_swap, c_drop
+```c
// Safe macro for swapping internals of two objects of same type:
c_swap(cmap_int, &map1, &map2);
diff --git a/include/stc/carc.h b/include/stc/carc.h
index d606ac6e..02bbaf52 100644
--- a/include/stc/carc.h
+++ b/include/stc/carc.h
@@ -160,6 +160,12 @@ STC_INLINE _cx_self _cx_memb(_clone)(_cx_self ptr) {
return ptr;
}
+// take ownership of unowned
+STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self unowned) {
+ _cx_memb(_drop)(self);
+ *self = unowned;
+}
+// share ownership with ptr
STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) {
if (ptr.use_count)
_i_atomic_inc(ptr.use_count);
@@ -167,12 +173,6 @@ STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self ptr) {
*self = ptr;
}
-STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self unowned) {
- if (self->get != unowned.get)
- _cx_memb(_drop)(self);
- *self = unowned;
-}
-
#ifndef i_no_cmp
STC_INLINE int _cx_memb(_raw_cmp)(const _cx_raw* rx, const _cx_raw* ry)
{ return i_cmp(rx, ry); }
diff --git a/include/stc/cbox.h b/include/stc/cbox.h
index 44c819dd..641fcbfc 100644
--- a/include/stc/cbox.h
+++ b/include/stc/cbox.h
@@ -145,18 +145,18 @@ STC_INLINE _cx_self _cx_memb(_from)(_cx_value val)
}
#endif // !i_no_clone
+// take ownership of unowned
STC_INLINE void _cx_memb(_take)(_cx_self* self, _cx_self unowned) {
- if (unowned.get != self->get)
- _cx_memb(_drop)(self);
+ _cx_memb(_drop)(self);
*self = unowned;
}
-/* transfer ownership; set dying to NULL */
-STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self* dying) {
- if (dying->get == self->get)
+// transfer ownership from moved; set moved to NULL
+STC_INLINE void _cx_memb(_assign)(_cx_self* self, _cx_self* moved) {
+ if (moved->get == self->get)
return;
_cx_memb(_drop)(self);
- *self = *dying;
- dying->get = NULL;
+ *self = *moved;
+ moved->get = NULL;
}
#ifndef i_no_cmp
diff --git a/include/stc/ccommon.h b/include/stc/ccommon.h
index dae991ed..711a9c6d 100644
--- a/include/stc/ccommon.h
+++ b/include/stc/ccommon.h
@@ -244,14 +244,26 @@ STC_INLINE char* cstrnstrn(const char *str, const char *needle,
if (it.ref == _endref) it.ref = NULL; \
} while (0)
+// use with: clist, cmap, cset, csmap, csset, cstr:
#define c_erase_if(it, C, cnt, pred) do { \
- C##_iter it = C##_begin(&cnt); \
- for (intptr_t index = 0; it.ref; ++index) { \
- if (pred) it = C##_erase_at(&cnt, it); \
+ C* _cnt = &cnt; \
+ for (C##_iter it = C##_begin(_cnt); it.ref;) { \
+ if (pred) it = C##_erase_at(_cnt, it); \
else C##_next(&it); \
} \
} while (0)
+// use with: cstack, cvec, cdeq, cqueue:
+#define c_eraseremove_if(it, C, cnt, pred) do { \
+ C* _cnt = &cnt; \
+ intptr_t _n = 0; \
+ C##_iter _first = C##_begin(_cnt), it = _first; \
+ for (; it.ref; C##_next(&it)) \
+ if (pred) ++_n; \
+ else C##_value_drop(_first.ref), *_first.ref = *it.ref, C##_next(&_first); \
+ _cnt->_len -= _n; \
+} while (0)
+
#endif // CCOMMON_H_INCLUDED
#undef STC_API
diff --git a/include/stc/cdeq.h b/include/stc/cdeq.h
index fd508bf6..8ca06ada 100644
--- a/include/stc/cdeq.h
+++ b/include/stc/cdeq.h
@@ -52,6 +52,7 @@ STC_INLINE void _cx_memb(_put_n)(_cx_self* self, const _cx_raw* raw, int
{ while (n--) _cx_memb(_push)(self, i_keyfrom(*raw++)); }
STC_INLINE _cx_self _cx_memb(_from_n)(const _cx_raw* raw, intptr_t n)
{ _cx_self cx = {0}; _cx_memb(_put_n)(&cx, raw, n); return cx; }
+STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
#if !defined _i_queue
#if !defined i_no_emplace
STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
diff --git a/include/stc/cstack.h b/include/stc/cstack.h
index 54bf7850..f0c930e5 100644
--- a/include/stc/cstack.h
+++ b/include/stc/cstack.h
@@ -82,7 +82,6 @@ STC_INLINE void _cx_memb(_drop)(_cx_self* self) {
i_free(self->data);
#endif
}
-
STC_INLINE intptr_t _cx_memb(_size)(const _cx_self* self)
{ return self->_len; }
@@ -96,6 +95,8 @@ STC_INLINE intptr_t _cx_memb(_capacity)(const _cx_self* self) {
return i_capacity;
#endif
}
+STC_INLINE void _cx_memb(_value_drop)(_cx_value* val)
+ { i_keydrop(val); }
STC_INLINE bool _cx_memb(_reserve)(_cx_self* self, intptr_t n) {
if (n < self->_len) return true;
diff --git a/include/stc/cvec.h b/include/stc/cvec.h
index 84c91228..88153912 100644
--- a/include/stc/cvec.h
+++ b/include/stc/cvec.h
@@ -92,6 +92,7 @@ STC_API int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value
STC_API _cx_iter _cx_memb(_find_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw);
STC_API _cx_iter _cx_memb(_binary_search_in)(_cx_iter it1, _cx_iter it2, _cx_raw raw, _cx_iter* lower_bound);
#endif
+STC_INLINE void _cx_memb(_value_drop)(_cx_value* val) { i_keydrop(val); }
#if !defined i_no_emplace
STC_API _cx_iter _cx_memb(_emplace_range)(_cx_self* self, _cx_value* pos,
@@ -413,8 +414,7 @@ _cx_memb(_binary_search_in)(_cx_iter i1, _cx_iter i2, const _cx_raw raw,
i1.ref = NULL; return i1;
}
-STC_DEF int
-_cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) {
+STC_DEF int _cx_memb(_value_cmp)(const _cx_value* x, const _cx_value* y) {
const _cx_raw rx = i_keyto(x);
const _cx_raw ry = i_keyto(y);
return i_cmp((&rx), (&ry));
diff --git a/misc/examples/box2.c b/misc/examples/box2.c
index 943b2ae8..f7d21976 100644
--- a/misc/examples/box2.c
+++ b/misc/examples/box2.c
@@ -1,36 +1,31 @@
-// https://doc.rust-lang.org/rust-by-example/std/box.html
-
-#include <stdlib.h>
+// example: https://doc.rust-lang.org/rust-by-example/std/box.html
#include <stdio.h>
-#include <string.h>
-#include <stc/ccommon.h>
-struct {
+typedef struct {
double x;
double y;
-} typedef Point;
+} Point;
// A Rectangle can be specified by where its top left and bottom right
// corners are in space
-struct {
+typedef struct {
Point top_left;
Point bottom_right;
-} typedef Rectangle;
+} Rectangle;
#define i_val Point
-#define i_opt c_no_cmp
+#define i_no_cmp
#include <stc/cbox.h> // cbox_Point
#define i_val Rectangle
-#define i_opt c_no_cmp
+#define i_no_cmp
#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_cmp
-#include <stc/cbox.h> // cbox_BoxPoint
+#define i_valboxed cbox_Point // NB: use i_valboxed when value is a cbox or carc!
+#define i_type BoxBoxPoint
+#define i_no_cmp
+#include <stc/cbox.h> // BoxBoxPoint
Point origin(void) {
return (Point){ .x=1.0, .y=2.0 };
@@ -38,7 +33,7 @@ Point origin(void) {
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 });
+ return cbox_Point_make((Point){ .x=1.0, .y=2.0 });
}
@@ -47,44 +42,47 @@ int main(void) {
Point point = origin();
Rectangle rectangle = (Rectangle){
.top_left = origin(),
- .bottom_right = (Point){ .x=3.0, .y=-4.0 }
+ .bottom_right = { .x=3.0, .y=-4.0 }
};
- // Declare auto-deleted box objects
+ // Declare RAII'ed box objects
c_auto (cbox_Rectangle, boxed_rectangle)
c_auto (cbox_Point, boxed_point)
- c_auto (cbox_BoxPoint, box_in_a_box, boxbox2)
+ c_auto (BoxBoxPoint, box_in_a_box)
{
// Heap allocated rectangle
boxed_rectangle = cbox_Rectangle_make((Rectangle){
.top_left = origin(),
- .bottom_right = (Point){ .x=3.0, .y=-4.0 }
+ .bottom_right = { .x=3.0, .y=-4.0 }
});
// The output of functions can be boxed
- boxed_point = cbox_Point_from(origin());
+ boxed_point = cbox_Point_make(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_in_a_box = BoxBoxPoint_make(boxed_origin());
+ //printf("box_in_a_box: x = %g\n", box_in_a_box.get->get->x);
+
+ // Can use from(raw) and toraw instead:
+ box_in_a_box = BoxBoxPoint_from(origin());
+ printf("box_in_a_box: x = %g\n", BoxBoxPoint_toraw(&box_in_a_box).x);
+
+ printf("Point occupies %d bytes on the stack\n",
+ (int)sizeof(point));
+ printf("Rectangle occupies %d bytes on the stack\n",
+ (int)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));
+ printf("Boxed point occupies %d bytes on the stack\n",
+ (int)sizeof(boxed_point));
+ printf("Boxed rectangle occupies %d bytes on the stack\n",
+ (int)sizeof(boxed_rectangle));
+ printf("Boxed box occupies %d bytes on the stack\n",
+ (int)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));
+ printf("Unboxed point occupies %d bytes on the stack\n",
+ (int)sizeof(unboxed_point));
}
}
diff --git a/misc/examples/list.c b/misc/examples/list.c
index 6a655800..b345bd16 100644
--- a/misc/examples/list.c
+++ b/misc/examples/list.c
@@ -17,6 +17,7 @@ int main() {
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)
@@ -46,18 +47,21 @@ int main() {
const double* v = clist_fx_get(&list, 30);
printf("found: %f\n", *v);
- c_foreach (i, clist_fx, list) printf(" %g", *i.ref);
+ 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: ");
+ clist_fx_iter it = clist_fx_begin(&list);
c_foreach (i, clist_fx, clist_fx_advance(it, 4), clist_fx_end(&list))
printf(" %g", *i.ref);
puts("");