From bb8484be936d82f0f01b99ca67a6de1508037e8f Mon Sep 17 00:00:00 2001 From: Tyge Løvset Date: Thu, 19 May 2022 11:22:03 +0200 Subject: Added _toval() in carc and cbox. Added dynamic polymorphism example, shape.c. --- examples/shape.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ include/stc/carc.h | 3 ++ include/stc/cbox.h | 3 ++ include/stc/template.h | 2 + 4 files changed, 142 insertions(+) create mode 100644 examples/shape.c diff --git a/examples/shape.c b/examples/shape.c new file mode 100644 index 00000000..7dc52759 --- /dev/null +++ b/examples/shape.c @@ -0,0 +1,134 @@ +// Demo of typesafe polymorphism in C99, using STC. + +#include +#include +#include + +#define c_self(s, T, vtable) \ + T* self = c_container_of(s, T, vtable) +#define c_is_first(T, memb) \ + c_static_assert(offsetof(T, memb) == 0) + + +typedef struct { float x, y; } Point; + +typedef struct Shape { + void (*drop)(struct Shape**); + void (*draw)(struct Shape**); +} Shape; + +void Shape_drop(Shape** shape) +{ +} + +void Shape_delete(Shape** shape) +{ + if (shape) { + (*shape)->drop(shape); + c_free(shape); + } +} + +// Triangle implementation +// ============================================================ + +typedef struct { + Shape* api; + Point p[3]; +} Triangle; + +c_is_first(Triangle, api); + + +void Triangle_draw(Shape** shape) +{ + const c_self(shape, Triangle, api); + printf("Triangle: (%g,%g), (%g,%g), (%g,%g)\n", + self->p[0].x, self->p[0].y, + self->p[1].x, self->p[1].y, + self->p[2].x, self->p[2].y); +} + +static Shape Triangle_api = { + .drop = Shape_drop, + .draw = Triangle_draw, +}; + +Shape** Triangle_new(Point a, Point b, Point c) +{ + Triangle* s = c_new(Triangle, {&Triangle_api, .p={a, b, c}}); + return &s->api; +} + +// Polygon implementation +// ============================================================ + +#define i_type PVec +#define i_val Point +#include + +typedef struct { + Shape* api; + PVec points; +} Polygon; + +c_is_first(Polygon, api); + + +void Polygon_drop(Shape** shape) +{ + puts("drop poly"); + c_self(shape, Polygon, api); + PVec_drop(&self->points); +} + +void Polygon_draw(Shape** shape) +{ + const c_self(shape, Polygon, api); + printf("Polygon:"); + c_foreach (i, PVec, self->points) + printf(" (%g,%g)", i.ref->x, i.ref->y); + puts(""); +} + +static Shape Polygon_api = { + .drop = Polygon_drop, + .draw = Polygon_draw, +}; + +Shape** Polygon_new(void) +{ + Polygon* s = c_new(Polygon, {&Polygon_api, .points=PVec_init()}); + return &s->api; +} + +void Polygon_addPoint(Shape** shape, Point p) +{ + c_self(shape, Polygon, api); + PVec_push(&self->points, p); +} + + +// Test +// ============================================================ + +void testShape(Shape** shape) +{ + (*shape)->draw(shape); +} + +int main(void) +{ + c_autovar (Shape** tria = NULL, Shape_delete(tria)) + c_autovar (Shape** poly = Polygon_new(), Shape_delete(poly)) + { + tria = Triangle_new((Point){5, 7}, (Point){12, 7}, (Point){12, 20}); + + c_apply(p, Polygon_addPoint(poly, p), Point, { + {5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}, + }); + + testShape(tria); + testShape(poly); + } +} diff --git a/include/stc/carc.h b/include/stc/carc.h index 6c591d2c..e4a69e80 100644 --- a/include/stc/carc.h +++ b/include/stc/carc.h @@ -115,6 +115,9 @@ STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) { return i_keyto(self->get); } +STC_INLINE _cx_value _cx_memb(_toval)(const _cx_self* self) + { return *self->get; } + STC_INLINE _cx_self _cx_memb(_move)(_cx_self* self) { _cx_self ptr = *self; self->get = NULL, self->use_count = NULL; diff --git a/include/stc/cbox.h b/include/stc/cbox.h index cb5cada3..73b437d4 100644 --- a/include/stc/cbox.h +++ b/include/stc/cbox.h @@ -97,6 +97,9 @@ STC_INLINE _cx_self _cx_memb(_make)(_cx_value val) { STC_INLINE _cx_raw _cx_memb(_toraw)(const _cx_self* self) { return i_keyto(self->get); } +STC_INLINE _cx_value _cx_memb(_toval)(const _cx_self* self) + { return *self->get; } + // destructor STC_INLINE void _cx_memb(_drop)(_cx_self* self) { if (self->get) { diff --git a/include/stc/template.h b/include/stc/template.h index f55a3354..6af10ace 100644 --- a/include/stc/template.h +++ b/include/stc/template.h @@ -114,6 +114,7 @@ #elif defined i_key_arcbox #define i_key_bind i_key_arcbox #define i_keyraw c_paste(i_key_arcbox, _value) + #define i_keyto c_paste(i_key, _toval) #define i_eq c_paste(i_key_arcbox, _value_eq) #endif @@ -196,6 +197,7 @@ #elif defined i_val_arcbox #define i_val_bind i_val_arcbox #define i_valraw c_paste(i_val_arcbox, _value) + #define i_valto c_paste(i_val, _toval) #endif #ifdef i_val_bind -- cgit v1.2.3