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 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 examples/shape.c (limited to '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); + } +} -- cgit v1.2.3