b9188eca8d5522effe2c6536e0915da40f320cef
[lunaix-os.git] / lunaix-os / includes / lunaix / changeling.h
1 #ifndef __LUNAIX_CHANGELING_H
2 #define __LUNAIX_CHANGELING_H
3
4 #include <lunaix/types.h>
5 #include <lunaix/ds/llist.h>
6 #include <lunaix/spike.h>
7 #include <lunaix/ds/hstr.h>
8
9 #define CHLG_ID   (unsigned short)0x4c43
10
11 #define morphable(struct_name)              chlg_##struct_name
12 #define __morpher_id(struct_name, field)    morphable(struct_name)
13 #define morpher_id(morpher)                 __morpher_id(morpher)
14
15 enum changeling_idents
16 {
17     morphable(anon) = 0,
18     #include <listings/changeling.lst>
19 };
20
21 /**
22  * changeling - a proud changeling of her majesty :)
23  *              changeling reginae superbum
24  */
25 struct changeling 
26 {
27     struct {
28         union {
29             struct
30             {
31                 unsigned short sig;
32                 unsigned short ident;
33             };
34
35             unsigned int magic;
36         };
37     };
38
39     int ref;
40     unsigned int uid;
41     
42     struct changeling *parent;
43     struct llist_header sibs;
44     struct llist_header subs;
45     struct hstr name;
46 };
47
48 typedef struct changeling morph_t;
49
50 #define morphable_attrs(struct_name, field)     struct_name, field
51 #define morphed_ptr(ptr_like)                   ((morph_t*)__ptr(ptr_like))
52 #define morpher_uid(mobj)                       ((mobj)->uid)
53
54 #define __changeling_morph(parent, chlg, name, struct_name, field)             \
55     ({                                                                         \
56         changeling_init(parent, &(chlg), chlg_##struct_name, name);            \
57         &(chlg);                                                               \
58     })
59
60 #define __morph_type_of(chlg, struct_name, field)                              \
61         ((chlg)->ident == chlg_##struct_name)
62
63 #define __changeling_cast(chlg, struct_name, field)                            \
64         container_of(chlg, struct struct_name, field)
65
66 #define __changeling_try_reveal(chlg, struct_name, field)                      \
67     ({                                                                         \
68         struct struct_name* __r = NULL;                                        \
69         if (__changeling_of(chlg, struct_name, field))                         \
70             __r = __changeling_cast(chlg, struct_name, field);                 \
71         __r;                                                                   \
72     })
73
74 #define __changeling_reveal(chlg, struct_name, field)                          \
75     ({                                                                         \
76         struct struct_name* __r;                                               \
77         __r = __changeling_try_reveal(chlg, struct_name, field);               \
78         assert(__r); __r;                                                      \
79     })
80
81 #define __changeling_of(chlg, struct_name, field)                              \
82         (chlg && (chlg)->sig == CHLG_ID                                        \
83               && __morph_type_of(chlg, struct_name, field))
84
85
86 #define changeling_morph(parent, chlg, name, morpher)                          \
87             __changeling_morph(parent, chlg, name, morpher)
88
89
90 #define changeling_morph_anon(parent, chlg, morpher)                           \
91             __changeling_morph(parent, chlg, NULL, morpher)
92
93
94 #define is_changeling(maybe_chlg)                                              \
95             ((maybe_chlg) && morphed_ptr(maybe_chlg)->sig == CHLG_ID)
96
97
98 #define morph_type_of(chlg, morpher)                                           \
99             __morph_type_of(chlg, morpher)
100
101 #define changeling_of(chlg, morpher)                                           \
102             __changeling_of(chlg, morpher)
103
104 #define changeling_try_reveal(chlg, morpher)                                   \
105             __changeling_try_reveal(chlg, morpher)
106
107 #define changeling_reveal(chlg, morpher)                                       \
108             __changeling_reveal(chlg, morpher)
109
110 #define changeling_for_each(pos, n, parent)                                    \
111             llist_for_each(pos, n, &(parent)->subs, sibs)
112
113 static inline morph_t*
114 changeling_ref(morph_t* chlg)
115 {
116     return ({ chlg->ref++; chlg; });
117 }
118
119 static inline morph_t*
120 changeling_unref(morph_t* chlg)
121 {
122     assert(chlg->ref > 0);
123     return ({ chlg->ref--; chlg; });
124 }
125
126 static inline void
127 changeling_detach(morph_t* obj)
128 {
129     if (llist_empty(&obj->sibs)) {
130         return;
131     }
132
133     changeling_unref(obj);
134     llist_delete(&obj->sibs);
135 }
136
137 static inline morph_t*
138 changeling_attach(morph_t* parent, morph_t* obj)
139 {
140     changeling_detach(obj);
141
142     llist_append(&parent->subs, &obj->sibs);
143     obj->parent = parent;
144
145     return changeling_ref(obj);
146 }
147
148 static inline void
149 changeling_isolate(morph_t* obj)
150 {
151     changeling_detach(obj);
152     assert(obj->ref == 0);
153 }
154
155 void
156 changeling_init(morph_t* parent, morph_t* chlg, 
157                 unsigned int id, const char* name);
158
159 morph_t*
160 changeling_spawn(morph_t* parent, const char* name);
161
162 morph_t*
163 changeling_find(morph_t* parent, struct hstr* str);
164
165 morph_t*
166 changeling_get_at(morph_t* parent, int index);
167
168 morph_t*
169 changeling_setname(morph_t* chlg, const char* name);
170
171 #endif /* __LUNAIX_CHANGELING_H */