make rule for user header file install
[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 #define morpher_name(mobj)                      ((mobj)->name.value)
54
55 #define __changeling_morph(parent, chlg, name, struct_name, field)             \
56     ({                                                                         \
57         changeling_init(parent, &(chlg), chlg_##struct_name, name);            \
58         &(chlg);                                                               \
59     })
60
61 #define __morph_type_of(chlg, struct_name, field)                              \
62         ((chlg)->ident == chlg_##struct_name)
63
64 #define __changeling_cast(chlg, struct_name, field)                            \
65         container_of(chlg, struct struct_name, field)
66
67 #define __changeling_try_reveal(chlg, struct_name, field)                      \
68     ({                                                                         \
69         struct struct_name* __r = NULL;                                        \
70         if (__changeling_of(chlg, struct_name, field))                         \
71             __r = __changeling_cast(chlg, struct_name, field);                 \
72         __r;                                                                   \
73     })
74
75 #define __changeling_reveal(chlg, struct_name, field)                          \
76     ({                                                                         \
77         struct struct_name* __r;                                               \
78         __r = __changeling_try_reveal(chlg, struct_name, field);               \
79         assert(__r); __r;                                                      \
80     })
81
82 #define __changeling_of(chlg, struct_name, field)                              \
83         (chlg && (chlg)->sig == CHLG_ID                                        \
84               && __morph_type_of(chlg, struct_name, field))
85
86
87 #define changeling_morph(parent, chlg, name, morpher)                          \
88             __changeling_morph(parent, chlg, name, morpher)
89
90
91 #define changeling_morph_anon(parent, chlg, morpher)                           \
92             __changeling_morph(parent, chlg, NULL, morpher)
93
94
95 #define is_changeling(maybe_chlg)                                              \
96             ((maybe_chlg) && morphed_ptr(maybe_chlg)->sig == CHLG_ID)
97
98
99 #define morph_type_of(chlg, morpher)                                           \
100             __morph_type_of(chlg, morpher)
101
102 #define changeling_of(chlg, morpher)                                           \
103             __changeling_of(chlg, morpher)
104
105 #define changeling_try_reveal(chlg, morpher)                                   \
106             __changeling_try_reveal(chlg, morpher)
107
108 #define changeling_reveal(chlg, morpher)                                       \
109             __changeling_reveal(chlg, morpher)
110
111 #define changeling_for_each(pos, n, parent)                                    \
112             llist_for_each(pos, n, &(parent)->subs, sibs)
113
114 static inline morph_t*
115 changeling_ref(morph_t* chlg)
116 {
117     return ({ chlg->ref++; chlg; });
118 }
119
120 static inline morph_t*
121 changeling_unref(morph_t* chlg)
122 {
123     assert(chlg->ref > 0);
124     return ({ chlg->ref--; chlg; });
125 }
126
127 static inline void
128 changeling_detach(morph_t* obj)
129 {
130     if (llist_empty(&obj->sibs)) {
131         return;
132     }
133
134     changeling_unref(obj);
135     llist_delete(&obj->sibs);
136 }
137
138 static inline morph_t*
139 changeling_attach(morph_t* parent, morph_t* obj)
140 {
141     changeling_detach(obj);
142
143     llist_append(&parent->subs, &obj->sibs);
144     obj->parent = parent;
145
146     return changeling_ref(obj);
147 }
148
149 static inline void
150 changeling_isolate(morph_t* obj)
151 {
152     changeling_detach(obj);
153     assert(obj->ref == 0);
154 }
155
156 void
157 changeling_init(morph_t* parent, morph_t* chlg, 
158                 unsigned int id, const char* name);
159
160 morph_t*
161 changeling_spawn(morph_t* parent, const char* name);
162
163 morph_t*
164 changeling_find(morph_t* parent, struct hstr* str);
165
166 morph_t*
167 changeling_get_at(morph_t* parent, int index);
168
169 morph_t*
170 changeling_setname(morph_t* chlg, const char* name);
171
172 #endif /* __LUNAIX_CHANGELING_H */