summaryrefslogtreecommitdiffhomepage
path: root/misc/examples/algorithms/shape.c
diff options
context:
space:
mode:
author_Tradam <[email protected]>2023-09-08 01:29:47 +0000
committerGitHub <[email protected]>2023-09-08 01:29:47 +0000
commit3c76c7f3d5db3f9586a90d03f8fbb02d79de9acd (patch)
treeafbe4b540967223911f7c5de36559b82154f02f3 /misc/examples/algorithms/shape.c
parent0841165881871ee01b782129be681209aeed2423 (diff)
parent1a72205fe05c2375cfd380dd8381a8460d9ed8d1 (diff)
downloadSTC-modified-modified.tar.gz
STC-modified-modified.zip
Merge branch 'stclib:master' into modifiedHEADmodified
Diffstat (limited to 'misc/examples/algorithms/shape.c')
-rw-r--r--misc/examples/algorithms/shape.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/misc/examples/algorithms/shape.c b/misc/examples/algorithms/shape.c
new file mode 100644
index 00000000..bd4bdd5a
--- /dev/null
+++ b/misc/examples/algorithms/shape.c
@@ -0,0 +1,158 @@
+// Demo of typesafe polymorphism in C99, using STC.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stc/ccommon.h>
+
+#define DYN_CAST(T, s) \
+ (&T##_api == (s)->api ? (T*)(s) : (T*)0)
+
+// Shape definition
+// ============================================================
+
+typedef struct {
+ float x, y;
+} Point;
+
+typedef struct Shape Shape;
+
+struct ShapeAPI {
+ void (*drop)(Shape*);
+ void (*draw)(const Shape*);
+};
+
+struct Shape {
+ struct ShapeAPI* api;
+ uint32_t color;
+ uint16_t style;
+ uint8_t thickness;
+ uint8_t hardness;
+};
+
+void Shape_drop(Shape* shape)
+{
+ printf("shape destructed\n");
+}
+
+void Shape_delete(Shape* shape)
+{
+ if (shape) {
+ shape->api->drop(shape);
+ c_free(shape);
+ }
+}
+
+// Triangle implementation
+// ============================================================
+
+typedef struct {
+ Shape shape;
+ Point p[3];
+} Triangle;
+
+extern struct ShapeAPI Triangle_api;
+
+
+Triangle Triangle_from(Point a, Point b, Point c) {
+ Triangle t = {{&Triangle_api}, {a, b, c}};
+ return t;
+}
+
+static void Triangle_draw(const Shape* shape)
+{
+ const Triangle* self = DYN_CAST(Triangle, shape);
+ printf("Triangle : (%g,%g), (%g,%g), (%g,%g)\n",
+ (double)self->p[0].x, (double)self->p[0].y,
+ (double)self->p[1].x, (double)self->p[1].y,
+ (double)self->p[2].x, (double)self->p[2].y);
+}
+
+struct ShapeAPI Triangle_api = {
+ .drop = Shape_drop,
+ .draw = Triangle_draw,
+};
+
+// Polygon implementation
+// ============================================================
+
+#define i_type PointVec
+#define i_key Point
+#include <stc/cstack.h>
+
+typedef struct {
+ Shape shape;
+ PointVec points;
+} Polygon;
+
+extern struct ShapeAPI Polygon_api;
+
+
+Polygon Polygon_init(void) {
+ Polygon p = {{&Polygon_api}, {0}};
+ return p;
+}
+
+void Polygon_addPoint(Polygon* self, Point p)
+{
+ PointVec_push(&self->points, p);
+}
+
+static void Polygon_drop(Shape* shape)
+{
+ Polygon* self = DYN_CAST(Polygon, shape);
+ printf("poly destructed\n");
+ PointVec_drop(&self->points);
+}
+
+static void Polygon_draw(const Shape* shape)
+{
+ const Polygon* self = DYN_CAST(Polygon, shape);
+ printf("Polygon :");
+ c_foreach (i, PointVec, self->points)
+ printf(" (%g,%g)", (double)i.ref->x, (double)i.ref->y);
+ puts("");
+}
+
+struct ShapeAPI Polygon_api = {
+ .drop = Polygon_drop,
+ .draw = Polygon_draw,
+};
+
+// Test
+// ============================================================
+
+#define i_type Shapes
+#define i_key Shape*
+#define i_keydrop(x) Shape_delete(*x)
+#define i_no_clone
+#include <stc/cstack.h>
+
+void testShape(const Shape* shape)
+{
+ shape->api->draw(shape);
+}
+
+
+int main(void)
+{
+ Shapes shapes = {0};
+
+ Triangle* tri1 = c_new(Triangle, Triangle_from(c_LITERAL(Point){5, 7}, c_LITERAL(Point){12, 7}, c_LITERAL(Point){12, 20}));
+ Polygon* pol1 = c_new(Polygon, Polygon_init());
+ Polygon* pol2 = c_new(Polygon, Polygon_init());
+
+ c_forlist (i, Point, {{50, 72}, {123, 73}, {127, 201}, {828, 333}})
+ Polygon_addPoint(pol1, *i.ref);
+
+ c_forlist (i, Point, {{5, 7}, {12, 7}, {12, 20}, {82, 33}, {17, 56}})
+ Polygon_addPoint(pol2, *i.ref);
+
+ Shapes_push(&shapes, &tri1->shape);
+ Shapes_push(&shapes, &pol1->shape);
+ Shapes_push(&shapes, &pol2->shape);
+
+ c_foreach (i, Shapes, shapes)
+ testShape(*i.ref);
+
+ Shapes_drop(&shapes);
+}