wip
[henge/apc.git] / src / ir.c
1 /*!@file
2 \brief IR Memory Implementation
3 \details Intermediary memory management
4 \author Jordan Lavatai
5 \date Aug 2016
6 ----------------------------------------------------------------------------*/
7 /* Standard */
8 #include <stdlib.h> //exit, malloc
9 #include <stdio.h> //print
10 #include <stdarg.h> //va_args
11 #include <stdint.h> //uint64_t
12 #include <string.h> //memset, str*
13 /* Unicode */
14 #include <unistd.h> //u8_* functions
15 #include <unitypes.h> //uint8_t as a char
16 #include <unistr.h> //u32_cpy
17 /* Local */
18 #include "apc.h"
19 #include "ir.h"
20 /* Public */
21 int ir_init(void);
22 void ir_quit(void);
23 int ir_linker(void);
24 int ir_condenser(void);
25 /* Private */
26 extern //apc.c
27 long sys_pagesize;
28 static
29
30 static inline
31 struct ir_framebox_t* ir_set_add_framebox(struct ir_set_t*, uint8_t*);
32 static inline
33 void ir_quit_r(struct pagenode_t*);
34 static inline
35 int bytes_identical(uint8_t*,uint8_t*);
36
37 /* Enumerated types */
38 enum dtype { FSDAT, MSDAT, ADAT, LDAT, FBDAT };
39 enum ltype { OLINK, MLINK, VLINK, ALINK };
40 /* Set data mem */
41 struct ir_setdata_header_t
42 { enum dtype type;
43 uint8_t* src_filename, * data_name;
44 union ir_setdata_t* nextsib;
45 };
46 struct ir_frameinfo_t
47 { int facing, w, h; };
48 struct ir_framedata_t
49 { struct ir_setdata_header_t header;
50 struct ir_frameinfo_t frameinfo;
51 }** framedatas;
52 struct ir_framebox_t
53 { struct ir_setdata_header_t header;
54 struct ir_framedata_t framesheets[FACING_MAX];
55 struct ir_framedata_t mapsheets[FACING_MAX];
56 }** frameboxes;
57 struct ir_simplex_t
58 { struct ir_setdat_header_t header;
59 }** simplexes;
60 struct ir_link_t
61 { struct ir_setdat_header_t header;
62 struct ir_set_t* src, * trg;
63 enum ltype type;
64 }** links;
65 union ir_setdata_t
66 { struct ir_setdata_header_t header;
67 struct ir_framebox_t framebox;
68 struct ir_framedata_t framesheet;
69 struct ir_framedata_t mapsheet;
70 struct ir_simplex_t audio;
71 struct ir_link_t link;
72 };
73 struct ir_class_t
74 { struct ir_class_t* nextchild, * nextsib;
75 struct ir_set_t* root_set;
76 uint8_t* name;
77 }** classes;
78 struct ir_set_t
79 { struct ir_set_t* nextchild, * nextsib;
80 struct ir_class_t* class;
81 long long ref;
82 uint8_t* name;
83 struct framebox_t* frameboxes;
84 struct simplex_t* audio;
85 struct link_t* links;
86 }** sets;
87 /* Function-Like Macros */
88 #define do_warn() do { \
89 } while (0)
90 #define wprint(str) do { \
91 fprintf(stderr, str); \
92 do_warn(); \
93 } while (0)
94 #define wprintf(fmt,...) do { \
95 fprintf(stderr, fmt, __VA_ARGS__); \
96 do_warn(); \
97 } while (0)
98 #define do_error() do { \
99 exit(-1); \
100 } while (0)
101 #define eprint(str) do { \
102 fprintf(stderr, str); \
103 do_error(); \
104 } while (0)
105 #define eprintf(fmt,...) do { \
106 fprintf(stderr, fmt, __VA_ARGS__); \
107 do_error(); \
108 } while (0)
109 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
110
111
112 static
113 struct ir_class_t root_class = { .name = "." };
114
115 /* Init */
116 int ir_init
117 ( void )
118 { pagenode_root = calloc(struct pagenode_t*) calloc(PN_ALLOCSIZE);
119 if (pagenode_root == NULL)
120 return -1;
121 pagenode_root->head = pagenode_root->root;
122 pagenode_head = pagenode_root;
123 return 0;
124 }
125
126 /* Quit/Cleanup
127 Recursively clean pagenode linked list
128 */
129 void ir_quit
130 ( void )
131 { ir_quit_r(pagenode_root); }
132
133 static inline
134 void ir_quit_r
135 ( struct pagenode_t* pagenode )
136 { if (pagenode->next != NULL)
137 ir_quit_r(pagenode->next);
138 free(pagenode);
139 }
140
141 /* Link
142 */
143 int ir_linker
144 ( void )
145 { return 0; }
146
147 /* Condense
148 */
149 int ir_condenser
150 ( void )
151 { return 0; }
152
153 /* Return a pointer to the root class */
154 struct ir_class_t* ir_class_root
155 ( void )
156 { return &root_class; }
157
158 /* Add a subclass to a class
159 Attempts to create a new subclass in the provided class, returning
160 the class if it already exists
161 */
162 struct ir_class_t* ir_class_addchild
163 ( struct ir_class_t* class,
164 uint8_t* name
165 )
166 { struct ir_class_t* iter;
167 if (class->nextchild == NULL)
168 return class->nextchild = struct_alloc(ir_class_t);
169 iter = class->nextchild;
170 check:
171 if (bytes_identical(iter->name, name))
172 return iter;
173 if (iter->nextsib != NULL)
174 { iter = iter->nextsib;
175 goto check;
176 }
177 return iter->nextsib = struct_alloc(ir_class_t);
178 }
179
180 /* Add a set to a class
181 Attempts to create a new root set in the specified class, returning
182 the set if it already exists
183 */
184 struct ir_set_t* ir_class_addset
185 ( struct ir_class_t* class,
186 uint8_t* name
187 )
188 { struct ir_set_t* iter;
189 if (class->root_set == NULL)
190 return class->root_set = struct_alloc(ir_set_t);
191 iter = class->root_set;
192 check:
193 if (bytes_identical(iter->name, name))
194 return iter;
195 if (iter->nextsib != NULL)
196 { iter = iter->nextsib;
197 goto check;
198 }
199 return iter->nextsib = struct_alloc(ir_set_t);
200 }
201
202 /* Add a set to a set
203 Attempts to create a new subset of the specified set, returning the
204 child if it already exists
205 */
206 struct ir_set_t* ir_set_addchild
207 ( struct ir_set_t* set,
208 uint8_t* name
209 )
210 { struct ir_set_t* iter;
211 if (set->nextchild == NULL)
212 return set->nextchild = struct_alloc(ir_set_t);
213 iter = set->nextchild;
214 check:
215 if (bytes_identical(iter->name, name))
216 return iter;
217 if (iter->nextsib != NULL)
218 { iter = iter->nextsib;
219 goto check;
220 }
221 return iter->nextsib = struct_alloc(ir_set_t);
222 }
223
224 /* Add a framebox to a set
225 Attempts to create a new framebox of the specified set, returning
226 the framebox if it already exists
227 */
228 static inline
229 struct ir_framebox_t* ir_set_add_framebox
230 ( struct ir_set_t* set,
231 uint8_t* name
232 )
233 { struct ir_framebox_t* iter;
234 if (set->frameboxes == NULL)
235 return set->frameboxes = struct_alloc(ir_framebox_t);
236 iter = set->frameboxes;
237 check:
238 if (bytes_identical(iter->header.name, name))
239 return iter;
240 if (iter->header.nextsib != NULL)
241 { iter = iter->header.nextsib;
242 goto check;
243 }
244 return iter->header.nextsib = struct_alloc(ir_framebox_t);
245 }
246
247 /* Match two null-terminated bytestrings
248 Return 1 if the two bytestrings are identical, else 0
249 */
250 static inline
251 int bytes_identical
252 ( uint8_t* stra,
253 uint8_t* strb
254 )
255 { while (*stra && *strb)
256 if (*stra++ != *strb++)
257 return 0;
258 return *stra == *strb;
259 }
260
261 /* Assign Setdata to Set
262
263 */
264 void ir_set_assign_data
265 ( struct ir_set_t* set,
266 union ir_setdata_t* setdata
267 )
268 { struct ir_framebox_t* framebox;
269 struct ir_simplex_t* simplex;
270 struct ir_link_t* link;
271 switch (setdata->header.type)
272 { case FSDAT:
273 framebox = ir_set_add_framebox(set, setdata->header.name);
274 if (framebox->framesheets[setdata->framesheet.frameinfo.facing] != NULL)
275 wprintf("Duplicate framesheet [%i] %s\n",
276 setdata->framesheet.frameinfo.facing, setdata->header.data_name);
277 framebox->framesheets[setdata->framesheet.frameinfo.facing] = setdata->framesheet;
278 break;
279 case MSDAT:
280 framebox = ir_set_add_framebox(set, setdata->header.name);
281 if (framebox->mapsheets[setdata->mapsheet.frameinfo.facing] != NULL)
282 wprintf("Duplicate mapsheet [%i] %s\n",
283 setdata->mapsheet.frameinfo.facing, setdata->header.data_name);
284 framebox->mapsheets[setdata->mapsheet.frameinfo.facing] = setdata->mapsheet;
285 break;
286 case ADAT:
287 if (set->audio == NULL)
288 { set->audio = &setdata->audio;
289 return;
290 }
291 simplex = set->audio;
292 while (simplex->header.nextsib != NULL;)
293 if (bytes_identical(simplex->header.data_name, setdata->header.data_name))
294 { wprintf("Duplicate audio %s\n", setdata->header.data_name);
295 *simplex = setdata->audio;
296 return;
297 }
298 else
299 simplex = simplex->header.nextsib;
300 simplex->header.nextsib = &setdata->audio;
301 break;
302 case LDAT:
303 if (set->links == NULL)
304 { set->links = &setdata->link;
305 return;
306 }
307 link = set->links;
308 while (link->header.nextsib != NULL)
309 link = link->header.nextsib;
310 link->header.nextsib = &setdata->link;
311 break;
312 default:
313 fprintf(stderr, "Unknown setdata type %x\n", setdata->header.type);
314 exit(-1);
315 }
316 }
317
318 void ir_set_assign_ref
319 ( ir_set_t* set,
320 long long ref
321 )
322 { if (set->ref != 0)
323 wprintf("Ref override: 0x%x -> 0x%x for set %s\n",
324 set->ref, ref, set->name);
325 set->ref = ref;
326 //TODO: reflist_add(set);
327 }
328
329 void ir_data_assign_path
330 ( union ir_setdata_t* setdata,
331 uint8_t* path
332 )
333 { if (set->header.src_filename)
334 wprintf("Path override: %s -> %s for set %s\n",
335 set->header.src_filename, path, set->name);
336 set->header.src_filename = path;
337 //TODO: internal strdup, not assign (= path;)
338 }
339
340
341 //TODO: Macro ir_framsheet and mapsheet?
342 union ir_setdata_t* ir_framesheet
343 ( uint8_t* name,
344 apc_facing d,
345 int width,
346 int height
347 )
348 { struct ir_framedata_t* framesheet = struct_alloc(ir_framedata_t);
349 framesheet->header->type = FSDAT;
350 framesheet->header.data_name = name;
351 framesheet->frameinfo.facing = d;
352 framesheet->frameinfo.w = width;
353 framesheet->frameinfo.h = height;
354 return (union ir_setdata_t*) framesheet;
355 }
356
357 union ir_setdata_t* ir_mapsheet
358 ( uint8_t* name,
359 apc_facing d,
360 int width,
361 int height,
362 )
363 { struct ir_framedata_t* mapsheet = struct_alloc(ir_framedata_t);
364 mapsheet->header.type = MSDAT;
365 mapsheet->header.data_name = name;
366 mapsheet->frameinfo.facing = d;
367 mapsheet->frameinfo.w = width;
368 mapsheet->frameinfo.h = height;
369 return (union ir_setdata_t*) mapsheet;
370 }
371
372 union ir_setdata_t* ir_audio
373 ( uint8_t* name )
374 { struct ir_simplex_t* audio = struct_alloc(ir_simplex_t);
375 audio->header.type = ADAT;
376 audio->header.data_name = name;
377 return (union ir_setdata_t*) audio;
378 }
379
380
381 #define PN_ALLOCSIZE (sys_pagesize)
382 #define PN_HEADERSIZE() (sizeof(struct pagenode_t*) + sizeof(void*))
383 #define PN_MEMSIZE() (PN_ALLOCSIZE - PN_HEADERSIZE())
384 #define PN_HEADSIZE() (pagenode_head->head - pagenode_head->root)
385 #define PN_HEADSPACE() (PN_MEMSIZE() - PN_HEADSIZE())
386 struct pagenode_t {
387 struct pagenode_t* next;
388 char* head;
389 char root[];
390 }* pagenode_root, * pagenode_head;
391
392
393 static
394 void* stack_alloc(size_t bytes)
395 { if (!bytes)
396 { wprint("Attempting to allocate 0 bytes in stack_alloc");
397 return pagenode_head->head;
398 }
399 if (PN_HEADSPACE() < bytes)
400 { pagenode_head->next = (struct pagenode_t*) calloc(PN_ALLOCSIZE);
401 pagenode_head = pagenode_head->next;
402 pagenode_head->head = pagenode_head->root;
403 }
404 pagenode_head->head += bytes;
405 return (void*) pagenode_head->head - bytes;
406 }
407