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
;
40 enum dtype
{ FSDAT
, MSDAT
, ADAT
, LDAT
, FBDAT
};
41 enum ltype
{ OLINK
, MLINK
, VLINK
, ALINK
};
44 { struct ir_namelist_t
* nextsib
;
48 { struct ir_class_t
* root_class
;
49 struct ir_namelist_t
* namelist
, * namelist_head
;
52 { struct ir_classld_t
* classld
;
54 struct ir_namelist_t
* namelist
, * namelist_head
;
57 struct ir_setdata_header_t
59 uint8_t* src_filename
, * data_name
;
60 union ir_setdata_t
* nextsib
;
63 { int facing
, w
, h
; };
65 { struct ir_setdata_header_t header
;
66 struct ir_frameinfo_t frameinfo
;
69 { struct ir_setdata_header_t header
;
70 struct ir_framedata_t framesheets
[FACING_MAX
];
71 struct ir_framedata_t mapsheets
[FACING_MAX
];
73 struct ir_simplex_t
{ struct ir_setdata_header_t header
; };
75 { struct ir_setdata_header_t header
;
76 struct ir_classld_t
* classld
;
77 struct ir_setld_t
* setld
;
81 { struct ir_setdata_header_t header
;
82 struct ir_framebox_t framebox
;
83 struct ir_framedata_t framesheet
;
84 struct ir_framedata_t mapsheet
;
85 struct ir_simplex_t audio
;
86 struct ir_link_t link
;
89 { struct ir_class_t
* nextchild
, * nextsib
;
90 struct ir_set_t
* root_set
;
94 { struct ir_set_t
* nextchild
, * nextsib
;
95 struct ir_class_t
* class;
98 struct ir_framebox_t
* frameboxes
;
99 struct ir_simplex_t
* audio
;
100 struct ir_link_t
* links
;
104 int init_pagelist(struct pagelist_t
*,size_t);
106 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*, uint8_t*);
108 void ir_free_pagenodes(struct pagenode_t
*);
110 int bytes_identical(uint8_t*,uint8_t*);
112 void* stack_alloc(size_t);
114 uint8_t* name_alloc(uint8_t*);
116 union ir_setdata_t
* ir_framedata (enum dtype
,uint8_t*,apc_facing
,int,int);
117 /* Function-Like Macros */
118 #define do_warn() do { \
120 #define wprint(str) do { \
121 fprintf(stderr, str); \
124 #define wprintf(fmt,...) do { \
125 fprintf(stderr, fmt, __VA_ARGS__); \
128 #define do_error() do { \
131 #define eprint(str) do { \
132 fprintf(stderr, str); \
135 #define eprintf(fmt,...) do { \
136 fprintf(stderr, fmt, __VA_ARGS__); \
139 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
140 #define DATA_PAGESIZE (sys_pagesize)
141 #define NAME_PAGESIZE (APC_NAME_MAX * 1024)
142 #define PL_HEADERSIZE (sizeof(struct pagenode_header_t))
143 #define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)
144 #define PL_HEADMEM(_PL) (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))
149 struct pagelist_t datapages
, namepages
;
151 struct ir_class_t root_class
= { .name
= (uint8_t*)"." };
156 { if (init_pagelist(&datapages
, (size_t)DATA_PAGESIZE
))
157 eprint("Memory allocation error\n");
158 if (init_pagelist(&namepages
, (size_t)NAME_PAGESIZE
))
159 eprint("Memory allocation error\n");
165 ( struct pagelist_t
* pl
,
168 { pl
->pagesize
= size
;
169 pl
->root
= (struct pagenode_t
*) calloc(size
,1);
170 if (pl
->root
== NULL
)
172 pl
->root
->header
.head
= pl
->root
->root
;
178 Recursively clean pagenode linked list
182 { ir_free_pagenodes(datapages
.root
);
183 ir_free_pagenodes(namepages
.root
);
187 void ir_free_pagenodes
188 ( struct pagenode_t
* pagenode
)
189 { if (pagenode
->header
.next
!= NULL
)
190 ir_free_pagenodes(pagenode
->header
.next
);
206 /* Return a pointer to the root class */
207 struct ir_class_t
* ir_class_root
209 { return &root_class
; }
211 /* Add a subclass to a class
212 Attempts to create a new subclass in the provided class, returning
213 the class if it already exists
215 struct ir_class_t
* ir_class_addchild
216 ( struct ir_class_t
* class,
219 { struct ir_class_t
* iter
;
220 if (class->nextchild
== NULL
)
221 return class->nextchild
= struct_alloc(ir_class_t
);
222 iter
= class->nextchild
;
224 if (bytes_identical(iter
->name
, name
))
226 if (iter
->nextsib
!= NULL
)
227 { iter
= iter
->nextsib
;
230 iter
= struct_alloc(ir_class_t
);
231 iter
->nextsib
= class->nextchild
;
232 iter
->name
= name_alloc(name
);
233 return class->nextchild
= iter
;
236 /* Add a set to a class
237 Attempts to create a new root set in the specified class, returning
238 the set if it already exists
240 struct ir_set_t
* ir_class_addset
241 ( struct ir_class_t
* class,
244 { struct ir_set_t
* iter
;
245 if (class->root_set
== NULL
)
246 return class->root_set
= struct_alloc(ir_set_t
);
247 iter
= class->root_set
;
249 if (bytes_identical(iter
->name
, name
))
251 if (iter
->nextsib
!= NULL
)
252 { iter
= iter
->nextsib
;
255 iter
= struct_alloc(ir_set_t
);
256 iter
->nextsib
= class->root_set
;
257 iter
->name
= name_alloc(name
);
258 return class->root_set
= iter
;
261 /* Add a set to a set
262 Attempts to create a new subset of the specified set, returning the
263 child if it already exists
265 struct ir_set_t
* ir_set_addchild
266 ( struct ir_set_t
* set
,
269 { struct ir_set_t
* iter
;
270 if (set
->nextchild
== NULL
)
271 return set
->nextchild
= struct_alloc(ir_set_t
);
272 iter
= set
->nextchild
;
274 if (bytes_identical(iter
->name
, name
))
276 if (iter
->nextsib
!= NULL
)
277 { iter
= iter
->nextsib
;
280 iter
= struct_alloc(ir_set_t
);
281 iter
->nextsib
= set
->nextchild
;
282 iter
->name
= name_alloc(name
);
283 return set
->nextchild
= iter
;
286 /* Add a framebox to a set
287 Attempts to create a new framebox of the specified set, returning
288 the framebox if it already exists
291 struct ir_framebox_t
* ir_set_add_framebox
292 ( struct ir_set_t
* set
,
295 { struct ir_framebox_t
* iter
;
296 if (set
->frameboxes
== NULL
)
297 return set
->frameboxes
= struct_alloc(ir_framebox_t
);
298 iter
= set
->frameboxes
;
300 if (bytes_identical(iter
->header
.data_name
, name
))
302 if (iter
->header
.nextsib
!= NULL
)
303 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
306 iter
= struct_alloc(ir_framebox_t
);
307 iter
->header
.nextsib
= (union ir_setdata_t
*) set
->frameboxes
;
308 iter
->header
.data_name
= name_alloc(name
);
309 return set
->frameboxes
= iter
;
312 /* Match two null-terminated bytestrings
313 Return 1 if the two bytestrings are identical, else 0
324 } while (ca
&& ca
== cb
);
328 /* Assign Setdata to Set
331 void ir_set_assign_data
332 ( struct ir_set_t
* set
,
333 union ir_setdata_t
* setdata
335 { struct ir_framebox_t
* framebox
;
336 struct ir_simplex_t
* simplex
;
337 switch (setdata
->header
.type
)
339 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
340 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
341 wprintf("Duplicate framesheet [%i] %s\n",
342 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
343 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
346 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
347 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
348 wprintf("Duplicate mapsheet [%i] %s\n",
349 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
350 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
353 if (set
->audio
== NULL
)
354 { set
->audio
= (struct ir_simplex_t
*) setdata
;
357 simplex
= set
->audio
;
358 while (simplex
->header
.nextsib
!= NULL
)
359 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
360 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
361 *simplex
= setdata
->audio
;
362 //setdata is now a pointer to redundant, unused memory.
366 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
367 setdata
->audio
.header
.nextsib
= (union ir_setdata_t
*) set
->audio
;
368 set
->audio
= (struct ir_simplex_t
*) setdata
;
371 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
372 set
->links
= (struct ir_link_t
*) setdata
;
375 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
380 void ir_set_assign_ref
381 ( struct ir_set_t
* set
,
385 wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",
386 (long unsigned) set
->ref
, (long unsigned) ref
, set
->name
);
388 //TODO: reflist_add(set);
391 void ir_data_assign_path
392 ( union ir_setdata_t
* setdata
,
395 { if (setdata
->header
.src_filename
!= NULL
)
396 wprintf("Path override: %s -> %s for setdata %s\n",
397 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
398 setdata
->header
.src_filename
= name_alloc(path
);
401 union ir_setdata_t
* ir_framesheet
407 { return ir_framedata(FSDAT
, name
, d
, width
, height
); }
409 union ir_setdata_t
* ir_mapsheet
415 { return ir_framedata(MSDAT
, name
, d
, width
, height
); }
418 union ir_setdata_t
* ir_framedata
425 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
426 framedata
->header
.type
= type
;
427 framedata
->header
.data_name
= name_alloc(name
);
428 framedata
->frameinfo
.facing
= d
;
429 framedata
->frameinfo
.w
= width
;
430 framedata
->frameinfo
.h
= height
;
431 return (union ir_setdata_t
*) framedata
;
434 union ir_setdata_t
* ir_audio
436 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
437 audio
->header
.type
= ADAT
;
438 audio
->header
.data_name
= name_alloc(name
);
439 return (union ir_setdata_t
*) audio
;
443 /* Create classld that points to a class */
444 struct ir_classld_t
* ir_classld_from_class
445 ( struct ir_class_t
* class )
446 { struct ir_classld_t
* classld
;
447 classld
= struct_alloc(ir_classld_t
);
448 classld
->root_class
= class;
452 struct ir_setld_t
* ir_setld_from_ref
454 { struct ir_setld_t
* setld
;
455 setld
= struct_alloc(ir_setld_t
);
460 struct ir_setld_t
* ir_setld_from_classld
461 ( struct ir_classld_t
* classld
,
464 { struct ir_setld_t
* setld
;
465 setld
= struct_alloc(ir_setld_t
);
466 setld
->namelist
= struct_alloc(ir_namelist_t
);
467 setld
->namelist_head
= setld
->namelist
;
468 setld
->namelist_head
->name
= name_alloc(name
);
469 setld
->classld
= classld
;
473 struct ir_setld_t
* ir_setld_addchild
474 ( struct ir_setld_t
* setld
,
477 { if (setld
->namelist
== NULL
)
478 { setld
->namelist
= struct_alloc(ir_namelist_t
);
479 setld
->namelist_head
= setld
->namelist
;
482 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
483 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
485 setld
->namelist_head
->name
= name_alloc(name
);
489 union ir_setdata_t
* ir_link
490 ( enum ltype link_type
,
491 struct ir_setld_t
* setld
,
494 { struct ir_link_t
* link
;
495 link
= struct_alloc(ir_link_t
);
496 link
->header
.type
= LDAT
;
497 link
->type
= link_type
;
498 link
->classld
= setld
->classld
;
500 if (link_type
!= OLINK
&& name
!= NULL
)
501 link
->header
.data_name
= name_alloc(name
);
502 return (union ir_setdata_t
*) link
;
509 { if (!bytes
) //valid behavior to attain current head
510 return datapages
.head
->header
.head
;
511 if (PL_HEADMEM(datapages
) < bytes
)
512 { datapages
.head
->header
.next
= (struct pagenode_t
*) calloc(datapages
.pagesize
,1);
513 if (datapages
.head
->header
.next
== NULL
)
514 eprint("Memory allocation error \n");
515 datapages
.head
= datapages
.head
->header
.next
;
516 datapages
.head
->header
.head
= datapages
.head
->root
;
518 datapages
.head
->header
.head
+= bytes
;
519 return (void*) datapages
.head
->header
.head
- bytes
;
524 ( uint8_t* name_src
)
525 { uint8_t* iter
, * name
;
528 name
= (uint8_t*)namepages
.head
->header
.head
;
530 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& head_mem
; head_mem
--)
531 *(namepages
.head
->header
.head
)++ = *iter
++;
532 if (head_mem
== 0) //not enough room
533 { namepages
.head
->header
.next
= (struct pagenode_t
*) calloc(namepages
.pagesize
,1);
534 if (namepages
.head
->header
.next
== NULL
)
535 eprint("Memory allocation error\n");
536 namepages
.head
= namepages
.head
->header
.next
;
537 namepages
.head
->header
.head
= namepages
.head
->root
;
540 *(namepages
.head
->header
.head
)++ = '\0';