1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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",
self->p[0].x, self->p[0].y,
self->p[1].x, self->p[1].y,
self->p[2].x, self->p[2].y);
}
struct ShapeAPI Triangle_api = {
.drop = Shape_drop,
.draw = Triangle_draw,
};
// Polygon implementation
// ============================================================
#define i_type PointVec
#define i_val 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)", i.ref->x, i.ref->y);
puts("");
}
struct ShapeAPI Polygon_api = {
.drop = Polygon_drop,
.draw = Polygon_draw,
};
// Test
// ============================================================
#define i_type Shapes
#define i_val Shape*
#define i_valdrop(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((Point){5, 7}, (Point){12, 7}, (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);
}
|