summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTyge Løvset <[email protected]>2022-05-19 11:22:03 +0200
committerTyge Løvset <[email protected]>2022-05-19 11:22:03 +0200
commitbb8484be936d82f0f01b99ca67a6de1508037e8f (patch)
tree07167891bf7c153380894e33377dd48816dfba99
parent775d0b3fce76be7512671c711d4aa16a5fa34a40 (diff)
downloadSTC-modified-bb8484be936d82f0f01b99ca67a6de1508037e8f.tar.gz
STC-modified-bb8484be936d82f0f01b99ca67a6de1508037e8f.zip
Added _toval() in carc and cbox. Added dynamic polymorphism example, shape.c.
-rw-r--r--examples/shape.c134
-rw-r--r--include/stc/carc.h3
-rw-r--r--include/stc/cbox.h3
-rw-r--r--include/stc/template.h2
4 files changed, 142 insertions, 0 deletions
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 <stdlib.h>
+#include <stdio.h>
+#include <stc/ccommon.h>
+
+#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 <stc/cstack.h>
+
+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