2 \brief IR Memory Implementation
3 \details Intermediary memory management
6 ----------------------------------------------------------------------------*/
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*
14 #include <unistd.h> //u8_* functions
15 #include <unitypes.h> //uint8_t as a char
16 #include <unistr.h> //u32_cpy
24 int ir_condenser(void);
25 /* Memory allocation structures */
27 struct pagenode_header_t
{
28 struct pagenode_t
* next
;
32 struct pagenode_header_t header
;
36 struct pagenode_t
* root
, * head
;
41 { struct ir_namelist_t
* nextsib
;
45 { struct ir_class_t
* root_class
;
46 struct ir_namelist_t
* namelist
, * namelist_head
;
49 { struct ir_classld_t
* classld
;
51 struct ir_namelist_t
* namelist
, * namelist_head
;
54 struct ir_setdata_header_t
56 uint8_t* src_filename
, * data_name
;
57 union ir_setdata_t
* nextsib
;
60 { int facing
, w
, h
; };
62 { struct ir_setdata_header_t header
;
63 struct ir_frameinfo_t frameinfo
;
66 { struct ir_setdata_header_t header
;
67 struct ir_framedata_t framesheets
[FACING_MAX
];
68 struct ir_framedata_t mapsheets
[FACING_MAX
];
70 struct ir_simplex_t
{ struct ir_setdata_header_t header
; };
72 { struct ir_setdata_header_t header
;
73 struct ir_classld_t
* classld
;
74 struct ir_setld_t
* setld
;
78 { struct ir_setdata_header_t header
;
79 struct ir_framebox_t framebox
;
80 struct ir_framedata_t framesheet
;
81 struct ir_framedata_t mapsheet
;
82 struct ir_simplex_t audio
;
83 struct ir_link_t link
;
86 { struct ir_class_t
* nextchild
, * nextsib
;
87 struct ir_set_t
* root_set
;
91 { struct ir_set_t
* nextchild
, * nextsib
;
92 struct ir_class_t
* class;
95 struct ir_framebox_t
* frameboxes
;
96 struct ir_simplex_t
* audio
;
97 struct ir_link_t
* links
;
101 int init_pagelist(struct pagelist_t
*,size_t);
103 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*, uint8_t*);
105 void ir_free_pagenodes(struct pagenode_t
*);
107 int bytes_identical(uint8_t*,uint8_t*);
109 void* stack_alloc(size_t);
111 uint8_t* name_alloc(uint8_t*);
113 union ir_setdata_t
* ir_framedata (enum dtype
,uint8_t*,apc_facing
,int,int);
114 /* Function-Like Macros */
115 #define do_warn() do { \
117 #define wprint(str) do { \
118 fprintf(stderr, str); \
121 #define wprintf(fmt,...) do { \
122 fprintf(stderr, fmt, __VA_ARGS__); \
125 #define do_error() do { \
128 #define eprint(str) do { \
129 fprintf(stderr, str); \
132 #define eprintf(fmt,...) do { \
133 fprintf(stderr, fmt, __VA_ARGS__); \
136 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
137 #define DATA_PAGESIZE (sys_pagesize)
138 #define NAME_PAGESIZE (APC_NAME_MAX * 1024)
139 #define PL_HEADERSIZE (sizeof(struct pagenode_header_t))
140 #define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)
141 #define PL_HEADMEM(_PL) (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))
146 struct pagelist_t datapages
, namepages
;
148 struct ir_class_t root_class
= { .name
= (uint8_t*)"." };
153 { if (init_pagelist(&datapages
, (size_t)DATA_PAGESIZE
))
154 eprint("Memory allocation error\n");
155 if (init_pagelist(&namepages
, (size_t)NAME_PAGESIZE
))
156 eprint("Memory allocation error\n");
162 ( struct pagelist_t
* pl
,
165 { pl
->pagesize
= size
;
166 pl
->root
= (struct pagenode_t
*) calloc(size
,1);
167 if (pl
->root
== NULL
)
169 pl
->root
->header
.head
= pl
->root
->root
;
175 Recursively clean pagenode linked list
179 { ir_free_pagenodes(datapages
.root
);
180 ir_free_pagenodes(namepages
.root
);
184 void ir_free_pagenodes
185 ( struct pagenode_t
* pagenode
)
186 { if (pagenode
->header
.next
!= NULL
)
187 ir_free_pagenodes(pagenode
->header
.next
);
203 /* Return a pointer to the root class */
204 struct ir_class_t
* ir_class_root
206 { return &root_class
; }
208 /* Add a subclass to a class
209 Attempts to create a new subclass in the provided class, returning
210 the class if it already exists
212 struct ir_class_t
* ir_class_addchild
213 ( struct ir_class_t
* class,
216 { struct ir_class_t
* iter
;
217 if (class->nextchild
== NULL
)
218 return class->nextchild
= struct_alloc(ir_class_t
);
219 iter
= class->nextchild
;
221 if (bytes_identical(iter
->name
, name
))
223 if (iter
->nextsib
!= NULL
)
224 { iter
= iter
->nextsib
;
227 iter
= struct_alloc(ir_class_t
);
228 iter
->nextsib
= class->nextchild
;
229 iter
->name
= name_alloc(name
);
230 return class->nextchild
= iter
;
233 /* Add a set to a class
234 Attempts to create a new root set in the specified class, returning
235 the set if it already exists
237 struct ir_set_t
* ir_class_addset
238 ( struct ir_class_t
* class,
241 { struct ir_set_t
* iter
;
242 if (class->root_set
== NULL
)
243 return class->root_set
= struct_alloc(ir_set_t
);
244 iter
= class->root_set
;
246 if (bytes_identical(iter
->name
, name
))
248 if (iter
->nextsib
!= NULL
)
249 { iter
= iter
->nextsib
;
252 iter
= struct_alloc(ir_set_t
);
253 iter
->nextsib
= class->root_set
;
254 iter
->name
= name_alloc(name
);
255 return class->root_set
= iter
;
258 /* Add a set to a set
259 Attempts to create a new subset of the specified set, returning the
260 child if it already exists
262 struct ir_set_t
* ir_set_addchild
263 ( struct ir_set_t
* set
,
266 { struct ir_set_t
* iter
;
267 if (set
->nextchild
== NULL
)
268 return set
->nextchild
= struct_alloc(ir_set_t
);
269 iter
= set
->nextchild
;
271 if (bytes_identical(iter
->name
, name
))
273 if (iter
->nextsib
!= NULL
)
274 { iter
= iter
->nextsib
;
277 iter
= struct_alloc(ir_set_t
);
278 iter
->nextsib
= set
->nextchild
;
279 iter
->name
= name_alloc(name
);
280 return set
->nextchild
= iter
;
283 /* Add a framebox to a set
284 Attempts to create a new framebox of the specified set, returning
285 the framebox if it already exists
288 struct ir_framebox_t
* ir_set_add_framebox
289 ( struct ir_set_t
* set
,
292 { struct ir_framebox_t
* iter
;
293 if (set
->frameboxes
== NULL
)
294 return set
->frameboxes
= struct_alloc(ir_framebox_t
);
295 iter
= set
->frameboxes
;
297 if (bytes_identical(iter
->header
.data_name
, name
))
299 if (iter
->header
.nextsib
!= NULL
)
300 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
303 iter
= struct_alloc(ir_framebox_t
);
304 iter
->header
.nextsib
= (union ir_setdata_t
*) set
->frameboxes
;
305 iter
->header
.data_name
= name_alloc(name
);
306 return set
->frameboxes
= iter
;
309 /* Match two null-terminated bytestrings
310 Return 1 if the two bytestrings are identical, else 0
321 } while (ca
&& ca
== cb
);
325 /* Assign Setdata to Set
328 void ir_set_assign_data
329 ( struct ir_set_t
* set
,
330 union ir_setdata_t
* setdata
332 { struct ir_framebox_t
* framebox
;
333 struct ir_simplex_t
* simplex
;
334 switch (setdata
->header
.type
)
336 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
337 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
338 wprintf("Duplicate framesheet [%i] %s\n",
339 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
340 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
343 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
344 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
345 wprintf("Duplicate mapsheet [%i] %s\n",
346 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
347 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
350 if (set
->audio
== NULL
)
351 { set
->audio
= (struct ir_simplex_t
*) setdata
;
354 simplex
= set
->audio
;
355 while (simplex
->header
.nextsib
!= NULL
)
356 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
357 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
358 *simplex
= setdata
->audio
;
359 //setdata is now a pointer to redundant, unused memory.
363 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
364 setdata
->audio
.header
.nextsib
= (union ir_setdata_t
*) set
->audio
;
365 set
->audio
= (struct ir_simplex_t
*) setdata
;
368 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
369 set
->links
= (struct ir_link_t
*) setdata
;
372 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
377 void ir_set_assign_ref
378 ( struct ir_set_t
* set
,
382 wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",
383 (long unsigned) set
->ref
, (long unsigned) ref
, set
->name
);
385 //TODO: reflist_add(set);
388 void ir_data_assign_path
389 ( union ir_setdata_t
* setdata
,
392 { if (setdata
->header
.src_filename
!= NULL
)
393 wprintf("Path override: %s -> %s for setdata %s\n",
394 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
395 setdata
->header
.src_filename
= name_alloc(path
);
398 union ir_setdata_t
* ir_framesheet
404 { return ir_framedata(FSDAT
, name
, d
, width
, height
); }
406 union ir_setdata_t
* ir_mapsheet
412 { return ir_framedata(MSDAT
, name
, d
, width
, height
); }
415 union ir_setdata_t
* ir_framedata
422 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
423 framedata
->header
.type
= type
;
424 framedata
->header
.data_name
= name_alloc(name
);
425 framedata
->frameinfo
.facing
= d
;
426 framedata
->frameinfo
.w
= width
;
427 framedata
->frameinfo
.h
= height
;
428 return (union ir_setdata_t
*) framedata
;
431 union ir_setdata_t
* ir_audio
433 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
434 audio
->header
.type
= ADAT
;
435 audio
->header
.data_name
= name_alloc(name
);
436 return (union ir_setdata_t
*) audio
;
440 /* Create classld that points to a class */
441 struct ir_classld_t
* ir_classld_from_class
442 ( struct ir_class_t
* class )
443 { struct ir_classld_t
* classld
;
444 classld
= struct_alloc(ir_classld_t
);
445 classld
->root_class
= class;
449 struct ir_setld_t
* ir_setld_from_ref
451 { struct ir_setld_t
* setld
;
452 setld
= struct_alloc(ir_setld_t
);
457 struct ir_setld_t
* ir_setld_from_classld
458 ( struct ir_classld_t
* classld
,
461 { struct ir_setld_t
* setld
;
462 setld
= struct_alloc(ir_setld_t
);
463 setld
->namelist
= struct_alloc(ir_namelist_t
);
464 setld
->namelist_head
= setld
->namelist
;
465 setld
->namelist_head
->name
= name_alloc(name
);
466 setld
->classld
= classld
;
470 struct ir_setld_t
* ir_setld_addchild
471 ( struct ir_setld_t
* setld
,
474 { if (setld
->namelist
== NULL
)
475 { setld
->namelist
= struct_alloc(ir_namelist_t
);
476 setld
->namelist_head
= setld
->namelist
;
479 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
480 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
482 setld
->namelist_head
->name
= name_alloc(name
);
486 union ir_setdata_t
* ir_link
487 ( enum ltype link_type
,
488 struct ir_setld_t
* setld
,
491 { struct ir_link_t
* link
;
492 link
= struct_alloc(ir_link_t
);
493 link
->header
.type
= LDAT
;
494 link
->type
= link_type
;
495 link
->classld
= setld
->classld
;
497 if (link_type
!= OLINK
&& name
!= NULL
)
498 link
->header
.data_name
= name_alloc(name
);
499 return (union ir_setdata_t
*) link
;
506 { if (!bytes
) //valid behavior to attain current head
507 return datapages
.head
->header
.head
;
508 if (PL_HEADMEM(datapages
) < bytes
)
509 { datapages
.head
->header
.next
= (struct pagenode_t
*) calloc(datapages
.pagesize
,1);
510 if (datapages
.head
->header
.next
== NULL
)
511 eprint("Memory allocation error \n");
512 datapages
.head
= datapages
.head
->header
.next
;
513 datapages
.head
->header
.head
= datapages
.head
->root
;
515 datapages
.head
->header
.head
+= bytes
;
516 return (void*) datapages
.head
->header
.head
- bytes
;
521 ( uint8_t* name_src
)
522 { uint8_t* iter
, * name
;
525 name
= (uint8_t*)namepages
.head
->header
.head
;
527 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& head_mem
; head_mem
--)
528 *(namepages
.head
->header
.head
)++ = *iter
++;
529 if (head_mem
== 0) //not enough room
530 { namepages
.head
->header
.next
= (struct pagenode_t
*) calloc(namepages
.pagesize
,1);
531 if (namepages
.head
->header
.next
== NULL
)
532 eprint("Memory allocation error\n");
533 namepages
.head
= namepages
.head
->header
.next
;
534 namepages
.head
->header
.head
= namepages
.head
->root
;
537 *(namepages
.head
->header
.head
)++ = '\0';