f5725936 |
1 | #include <stdio.h> |
2 | #include <malloc.h> |
3 | #include <assert.h> |
4 | |
5 | #define CONFEDERATION(IFACE,TYPE) struct IFACE *interface;struct TYPE *next |
6 | #define CREATE(TYPE) (struct TYPE *)malloc(sizeof(struct TYPE)) |
7 | #define APPEND(TYPE,MEMBER,LIST) (MEMBER?MEMBER->next=(struct TYPE *)LIST:0,LIST=(struct TYPE *)MEMBER) |
8 | #define SELF void *_self, void *_dummy |
9 | #define I_AM(TYPE) struct TYPE *self=(struct TYPE *)_self; |
10 | |
11 | struct Drawable_data |
12 | { |
13 | CONFEDERATION(Drawable_interface,Drawable_data); |
14 | }; |
15 | |
16 | struct Drawable_interface |
17 | { |
18 | void (*draw)(SELF); |
19 | int (*desc)(SELF, int something); |
20 | }; |
21 | |
22 | struct Tri |
23 | { |
24 | CONFEDERATION(Drawable_interface,Drawable_data); |
25 | int x1; int y1; int x2; int y2; int x3; int y3; |
26 | }; |
27 | |
28 | struct Rect |
29 | { |
30 | CONFEDERATION(Drawable_interface,Drawable_data); |
31 | int x1; int y1; int x2; int y2; |
32 | }; |
33 | |
34 | void draw_tri(SELF) |
35 | { |
36 | I_AM(Tri); |
37 | printf("imagine I am drawing %d,%d - %d,%d - %d,%d\n",self->x1,self->y1,self->x2,self->y2,self->x3,self->y3); |
38 | }; |
39 | |
40 | void draw_rect(SELF) |
41 | { |
42 | I_AM(Rect); |
43 | printf("imagine I am drawing %d,%d - %d,%d\n",self->x1,self->y1,self->x2,self->y2); |
44 | }; |
45 | |
46 | int desc_tri(SELF, int something) |
47 | { |
48 | I_AM(Tri); |
49 | printf("I am triangle %d,%d - %d,%d - %d,%d, method draw called with argument: %d\n",self->x1,self->y1,self->x2,self->y2,self->x3,self->y3, something); |
50 | return something; |
51 | }; |
52 | |
53 | int desc_rect(SELF, int something) |
54 | { |
55 | I_AM(Rect); |
56 | printf("I am rectangle %d,%d - %d,%d, method draw called with argument: %d\n",self->x1,self->y1,self->x2,self->y2, something); |
57 | return something; |
58 | }; |
59 | |
60 | struct Drawable_interface *init_tri_interface(void) |
61 | { |
62 | struct Drawable_interface *i=CREATE(Drawable_interface); |
63 | /* vsechny metody je bohuzel potreba bindnout rucne, neda se svitit... */ |
64 | if(i) { i->draw=draw_tri; i->desc=desc_tri; } |
65 | return i; |
66 | } |
67 | |
68 | struct Drawable_interface *init_rect_interface(void) |
69 | { |
70 | struct Drawable_interface *i=CREATE(Drawable_interface); |
71 | /* vsechny metody je bohuzel potreba bindnout rucne, neda se svitit... */ |
72 | if(i) { i->draw=draw_rect; i->desc=desc_rect; } |
73 | return i; |
74 | } |
75 | |
76 | struct Tri *create_tri(struct Drawable_interface *i, int x1, int y1, int x2, int y2, int x3, int y3) |
77 | { |
78 | struct Tri *t=CREATE(Tri); |
79 | if(i && t) |
80 | { |
81 | t->interface=i; |
82 | t->x1=x1;t->y1=y1;t->x2=x2;t->y2=y2;t->x3=x3;t->y3=y3; |
83 | } |
84 | return t; |
85 | } |
86 | |
87 | struct Rect *create_rect(struct Drawable_interface *i, int x1, int y1, int x2, int y2) |
88 | { |
89 | struct Rect *r=CREATE(Rect); |
90 | if(i && r) |
91 | { |
92 | r->interface=i; |
93 | r->x1=x1;r->y1=y1;r->x2=x2;r->y2=y2; |
94 | } |
95 | return r; |
96 | } |
97 | |
98 | int main(void) |
99 | { |
100 | struct Drawable_interface *tri_interface=init_tri_interface(); |
101 | struct Drawable_interface *rect_interface=init_rect_interface(); |
102 | struct Drawable_data *all=NULL,*one; |
103 | struct Tri *t; |
104 | struct Rect *r; |
105 | |
106 | r=create_rect(rect_interface,0,10,1,11); |
107 | APPEND(Drawable_data,r,all); |
108 | t=create_tri(tri_interface,0,0,0,4,3,0); |
109 | APPEND(Drawable_data,t,all); |
110 | r=create_rect(rect_interface,10,0,11,1); |
111 | APPEND(Drawable_data,r,all); |
112 | |
113 | /* a nyni ... bylo to hodne prace, ale povedlo se ... ! */ |
114 | |
115 | for(one=all;one;one=one->next) |
116 | { |
117 | printf("(return value %d)\n",(*(one->interface->desc)) (one,NULL,0)); |
118 | (*(one->interface->draw)) (one,NULL); |
119 | } |
120 | |
121 | /* ...a nakonec pro efekt jeste instatni nudlovy kod s kanci prichuti dle ANSI C99: */ |
122 | |
123 | #define _ARG1(ARG1,...) ARG1 |
124 | #define _(OBJECT,...) (assert(OBJECT),/**/(*(OBJECT->interface->_ARG1(__VA_ARGS__,)))/**/(OBJECT,OBJECT->interface->__VA_ARGS__)/**/) |
125 | #define FOR_EACH(ONE,ALL) for(ONE=ALL;ONE;ONE=ONE->next) |
126 | |
127 | FOR_EACH(one,all) |
128 | { |
129 | printf("(return value %d)\n",_(one,desc,1)); |
130 | _(one,draw); |
131 | } |
132 | |
133 | return 0; |
134 | } |