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
17 #include <unistdio.h> //ulc_fprintf
23 #define do_error(...) exit(-1)
28 int ir_condenser(void);
29 /* Memory allocation structures */
31 struct pagenode_header_t
{
32 struct pagenode_t
* next
;
36 struct pagenode_header_t header
;
40 struct pagenode_t
* root
, * head
;
43 #define DATA_PAGESIZE (sys_pagesize)
44 #define NAME_PAGESIZE (APC_NAME_MAX * 1024)
45 #define PL_HEADERSIZE (sizeof(struct pagenode_header_t))
46 #define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)
47 #define PL_HEADMEM(_PL) (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))
49 enum dtype
{ FSDAT
, MSDAT
, ADAT
, LDAT
, FBDAT
};
52 { struct ir_namelist_t
* nextsib
;
56 { struct ir_class_t
* root_class
;
57 struct ir_namelist_t
* namelist
, * namelist_head
;
60 { struct ir_classld_t
* classld
;
62 struct ir_namelist_t
* namelist
, * namelist_head
;
64 struct ir_setdata_header_t
66 uint8_t* src_filename
, * data_name
;
67 union ir_setdata_t
* nextsib
;
70 { int facing
, w
, h
; };
72 { struct ir_setdata_header_t header
;
73 struct ir_frameinfo_t frameinfo
;
76 { struct ir_setdata_header_t header
;
77 struct ir_framedata_t framesheets
[FACING_MAX
];
78 struct ir_framedata_t mapsheets
[FACING_MAX
];
80 struct ir_simplex_t
{ struct ir_setdata_header_t header
; };
82 { struct ir_setdata_header_t header
;
83 struct ir_classld_t
* classld
;
84 struct ir_setld_t
* setld
;
88 { struct ir_setdata_header_t header
;
89 struct ir_framebox_t framebox
;
90 struct ir_framedata_t framesheet
;
91 struct ir_framedata_t mapsheet
;
92 struct ir_simplex_t audio
;
93 struct ir_link_t link
;
96 { struct ir_class_t
* nextchild
, * nextsib
;
97 struct ir_set_t
* root_set
;
101 { struct ir_set_t
* nextchild
, * nextsib
;
102 struct ir_class_t
* class;
105 struct ir_framebox_t
* frameboxes
;
106 struct ir_simplex_t
* audio
;
107 struct ir_link_t
* links
;
111 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*,const uint8_t*);
113 union ir_setdata_t
* ir_framedata (enum dtype
,const uint8_t*,apc_facing
,int,int);
115 int init_pagelist(struct pagelist_t
*,size_t);
117 void ir_free_pagenodes(struct pagenode_t
*);
119 int bytes_identical(const uint8_t*,const uint8_t*);
121 int classnames_identical(const uint8_t*,const uint8_t*);
123 void* stack_alloc(size_t);
124 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
126 uint8_t* name_alloc(const uint8_t*);
128 uint8_t* classname_alloc(const uint8_t*);
132 struct pagelist_t datapages
, namepages
;
134 struct ir_class_t root_class
= { .name
= (uint8_t*)"." };
139 { if (init_pagelist(&datapages
, (size_t)DATA_PAGESIZE
))
140 eprintf("Memory allocation error\n");
141 if (init_pagelist(&namepages
, (size_t)NAME_PAGESIZE
))
142 eprintf("Memory allocation error\n");
148 ( struct pagelist_t
* pl
,
151 { pl
->pagesize
= size
;
152 pl
->root
= (struct pagenode_t
*) calloc(size
,1);
153 if (pl
->root
== NULL
)
155 pl
->root
->header
.head
= pl
->root
->root
;
161 Recursively clean pagenode linked list
165 { ir_free_pagenodes(datapages
.root
);
166 ir_free_pagenodes(namepages
.root
);
170 void ir_free_pagenodes
171 ( struct pagenode_t
* pagenode
)
172 { if (pagenode
->header
.next
!= NULL
)
173 ir_free_pagenodes(pagenode
->header
.next
);
189 /* Return the class's name string */
190 uint8_t* ir_class_name
191 ( struct ir_class_t
* class )
192 { return class->name
; }
194 /* Return a pointer to the root class */
195 struct ir_class_t
* ir_class_root
197 { return &root_class
; }
199 /* Add a subclass to a class
200 Attempts to create a new subclass in the provided class, returning
201 the class if it already exists
203 struct ir_class_t
* ir_class_addchild
204 ( struct ir_class_t
* class,
207 { struct ir_class_t
* iter
;
208 if (class->nextchild
== NULL
)
210 iter
= class->nextchild
;
211 if (iter
->name
== NULL
)
212 eprintf("Null name pointer in class %p\n", iter
);
214 eprintf("Null child added to class %s\n", iter
->name
);
216 if (classnames_identical(iter
->name
, name
))
218 if (iter
->nextsib
!= NULL
)
219 { iter
= iter
->nextsib
;
223 iter
= struct_alloc(ir_class_t
);
224 iter
->nextsib
= class->nextchild
;
225 iter
->name
= classname_alloc(name
);
226 return class->nextchild
= iter
;
229 /* Add a set to a class
230 Attempts to create a new root set in the specified class, returning
231 the set if it already exists
233 struct ir_set_t
* ir_class_addset
234 ( struct ir_class_t
* class,
237 { struct ir_set_t
* iter
;
238 if (class->root_set
== NULL
)
240 iter
= class->root_set
;
241 if (iter
->name
== NULL
)
242 eprintf("Null name pointer in class %p\n", iter
);
244 eprintf("Null set added to class %U\n", iter
->name
);
246 if (bytes_identical(iter
->name
, name
))
248 if (iter
->nextsib
!= NULL
)
249 { iter
= iter
->nextsib
;
253 iter
= struct_alloc(ir_set_t
);
254 iter
->nextsib
= class->root_set
;
255 iter
->name
= name_alloc(name
);
256 return class->root_set
= iter
;
259 /* Add a set to a set
260 Attempts to create a new subset of the specified set, returning the
261 child if it already exists
263 struct ir_set_t
* ir_set_addchild
264 ( struct ir_set_t
* set
,
267 { struct ir_set_t
* iter
;
268 if (set
->nextchild
== NULL
)
270 iter
= set
->nextchild
;
271 if (iter
->name
== NULL
)
272 eprintf("Null name pointer in set %p\n", iter
);
274 eprintf("Null child added to set %s\n", iter
->name
);
276 if (bytes_identical(iter
->name
, name
))
278 if (iter
->nextsib
!= NULL
)
279 { iter
= iter
->nextsib
;
283 iter
= struct_alloc(ir_set_t
);
284 iter
->nextsib
= set
->nextchild
;
285 iter
->name
= name_alloc(name
);
286 return set
->nextchild
= iter
;
289 /* Add a framebox to a set
290 Attempts to create a new framebox of the specified set, returning
291 the framebox if it already exists
294 struct ir_framebox_t
* ir_set_add_framebox
295 ( struct ir_set_t
* set
,
298 { struct ir_framebox_t
* iter
;
299 if (set
->frameboxes
== NULL
)
301 iter
= set
->frameboxes
;
303 if (bytes_identical(iter
->header
.data_name
, name
))
305 if (iter
->header
.nextsib
!= NULL
)
306 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
310 iter
= struct_alloc(ir_framebox_t
);
311 iter
->header
.nextsib
= (union ir_setdata_t
*) set
->frameboxes
;
312 iter
->header
.data_name
= name_alloc(name
);
313 return set
->frameboxes
= iter
;
316 /* Match two null-terminated bytestrings
317 Return 1 if the two bytestrings are identical, else 0
321 ( const uint8_t* stra
,
328 } while (ca
&& ca
!= '_' && ca
== cb
);
333 int classnames_identical
334 ( const uint8_t* stra
,
341 } while (ca
&& ca
== cb
);
345 /* Assign Setdata to Set
348 void ir_set_assign_data
349 ( struct ir_set_t
* set
,
350 union ir_setdata_t
* setdata
352 { struct ir_framebox_t
* framebox
;
353 struct ir_simplex_t
* simplex
;
354 switch (setdata
->header
.type
)
356 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
357 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
358 wprintf("Duplicate framesheet [%i] %s\n",
359 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
360 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
363 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
364 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
365 wprintf("Duplicate mapsheet [%i] %s\n",
366 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
367 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
370 if (set
->audio
== NULL
)
371 { set
->audio
= (struct ir_simplex_t
*) setdata
;
374 simplex
= set
->audio
;
375 while (simplex
->header
.nextsib
!= NULL
)
376 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
377 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
378 *simplex
= setdata
->audio
;
379 //setdata is now a pointer to redundant, unused memory.
383 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
384 setdata
->audio
.header
.nextsib
= (union ir_setdata_t
*) set
->audio
;
385 set
->audio
= (struct ir_simplex_t
*) setdata
;
388 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
389 set
->links
= (struct ir_link_t
*) setdata
;
392 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
397 void ir_set_assign_ref
398 ( struct ir_set_t
* set
,
402 wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",
403 (long unsigned) set
->ref
, (long unsigned) ref
, set
->name
);
405 //TODO: reflist_add(set);
408 void ir_data_assign_path
409 ( union ir_setdata_t
* setdata
,
413 eprintf("Null path in data %s\n", setdata
->header
.data_name
);
414 if (setdata
->header
.src_filename
!= NULL
)
415 wprintf("Path override: %s -> %s for setdata %s\n",
416 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
417 setdata
->header
.src_filename
= name_alloc(path
);
420 union ir_setdata_t
* ir_framesheet
421 ( const uint8_t* name
,
426 { return ir_framedata(FSDAT
, name
, d
, width
, height
); }
428 union ir_setdata_t
* ir_mapsheet
429 ( const uint8_t* name
,
434 { return ir_framedata(MSDAT
, name
, d
, width
, height
); }
437 union ir_setdata_t
* ir_framedata
444 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
446 eprintf("Null name in set allocation\n");
447 framedata
->header
.type
= type
;
448 framedata
->header
.data_name
= name_alloc(name
);
449 framedata
->frameinfo
.facing
= d
;
450 framedata
->frameinfo
.w
= width
;
451 framedata
->frameinfo
.h
= height
;
452 return (union ir_setdata_t
*) framedata
;
455 union ir_setdata_t
* ir_audio
456 ( const uint8_t* name
)
457 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
459 eprintf("Null audio\n");
460 audio
->header
.type
= ADAT
;
461 audio
->header
.data_name
= name_alloc(name
);
462 return (union ir_setdata_t
*) audio
;
466 /* Create classld that points to a class */
467 struct ir_classld_t
* ir_classld_from_class
468 ( struct ir_class_t
* class )
469 { struct ir_classld_t
* classld
;
471 eprintf("Null class in classld\n");
472 classld
= struct_alloc(ir_classld_t
);
473 classld
->root_class
= class;
477 struct ir_setld_t
* ir_setld_from_ref
479 { struct ir_setld_t
* setld
;
480 setld
= struct_alloc(ir_setld_t
);
485 struct ir_setld_t
* ir_setld_from_classld
486 ( struct ir_classld_t
* classld
,
489 { struct ir_setld_t
* setld
;
490 setld
= struct_alloc(ir_setld_t
);
491 setld
->namelist
= struct_alloc(ir_namelist_t
);
492 setld
->namelist_head
= setld
->namelist
;
493 setld
->namelist_head
->name
= name_alloc(name
);
494 setld
->classld
= classld
;
498 struct ir_setld_t
* ir_setld_addchild
499 ( struct ir_setld_t
* setld
,
502 { if (setld
->namelist
== NULL
)
503 { setld
->namelist
= struct_alloc(ir_namelist_t
);
504 setld
->namelist_head
= setld
->namelist
;
507 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
508 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
510 setld
->namelist_head
->name
= name_alloc(name
);
514 union ir_setdata_t
* ir_link
515 ( enum ltype link_type
,
516 struct ir_setld_t
* setld
,
519 { struct ir_link_t
* link
;
520 link
= struct_alloc(ir_link_t
);
521 link
->header
.type
= LDAT
;
522 link
->type
= link_type
;
523 link
->classld
= setld
->classld
;
525 if (link_type
!= OLINK
&& name
!= NULL
)
526 link
->header
.data_name
= name_alloc(name
);
527 return (union ir_setdata_t
*) link
;
534 { if (!bytes
) //valid behavior to attain current head
535 return datapages
.head
->header
.head
;
536 if (PL_HEADMEM(datapages
) < bytes
)
537 { datapages
.head
->header
.next
= (struct pagenode_t
*) calloc(datapages
.pagesize
,1);
538 if (datapages
.head
->header
.next
== NULL
)
539 eprintf("Memory allocation error \n");
540 datapages
.head
= datapages
.head
->header
.next
;
541 datapages
.head
->header
.head
= datapages
.head
->root
;
543 datapages
.head
->header
.head
+= bytes
;
544 return (void*) datapages
.head
->header
.head
- bytes
;
549 ( const uint8_t* name_src
)
550 { const uint8_t* iter
;
554 name
= (uint8_t*)namepages
.head
->header
.head
;
556 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& *iter
!= '_' && head_mem
; head_mem
--)
557 *(namepages
.head
->header
.head
)++ = *iter
++;
558 if (head_mem
== 0) //not enough room
559 { namepages
.head
->header
.next
= (struct pagenode_t
*) calloc(namepages
.pagesize
,1);
560 if (namepages
.head
->header
.next
== NULL
)
561 eprintf("Memory allocation error\n");
562 namepages
.head
= namepages
.head
->header
.next
;
563 namepages
.head
->header
.head
= namepages
.head
->root
;
566 *(namepages
.head
->header
.head
)++ = '\0';
571 uint8_t* classname_alloc
572 ( const uint8_t* name_src
)
573 { const uint8_t* iter
;
577 name
= (uint8_t*)namepages
.head
->header
.head
;
579 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& head_mem
; head_mem
--)
580 *(namepages
.head
->header
.head
)++ = *iter
++;
581 if (head_mem
== 0) //not enough room
582 { namepages
.head
->header
.next
= (struct pagenode_t
*) calloc(namepages
.pagesize
,1);
583 if (namepages
.head
->header
.next
== NULL
)
584 eprintf("Memory allocation error\n");
585 namepages
.head
= namepages
.head
->header
.next
;
586 namepages
.head
->header
.head
= namepages
.head
->root
;
589 *(namepages
.head
->header
.head
)++ = '\0';