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 void* stack_alloc(size_t);
122 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
124 uint8_t* name_alloc(const uint8_t*);
128 struct pagelist_t datapages
, namepages
;
130 struct ir_class_t root_class
= { .name
= (uint8_t*)"." };
135 { if (init_pagelist(&datapages
, (size_t)DATA_PAGESIZE
))
136 eprintf("Memory allocation error\n");
137 if (init_pagelist(&namepages
, (size_t)NAME_PAGESIZE
))
138 eprintf("Memory allocation error\n");
144 ( struct pagelist_t
* pl
,
147 { pl
->pagesize
= size
;
148 pl
->root
= (struct pagenode_t
*) calloc(size
,1);
149 if (pl
->root
== NULL
)
151 pl
->root
->header
.head
= pl
->root
->root
;
157 Recursively clean pagenode linked list
161 { ir_free_pagenodes(datapages
.root
);
162 ir_free_pagenodes(namepages
.root
);
166 void ir_free_pagenodes
167 ( struct pagenode_t
* pagenode
)
168 { if (pagenode
->header
.next
!= NULL
)
169 ir_free_pagenodes(pagenode
->header
.next
);
185 /* Return the class's name string */
186 uint8_t* ir_class_name
187 ( struct ir_class_t
* class )
188 { return class->name
; }
190 /* Return a pointer to the root class */
191 struct ir_class_t
* ir_class_root
193 { return &root_class
; }
195 /* Add a subclass to a class
196 Attempts to create a new subclass in the provided class, returning
197 the class if it already exists
199 struct ir_class_t
* ir_class_addchild
200 ( struct ir_class_t
* class,
203 { struct ir_class_t
* iter
;
204 if (class->nextchild
== NULL
)
206 iter
= class->nextchild
;
207 if (iter
->name
== NULL
)
208 eprintf("Null name pointer in class %p\n", iter
);
210 eprintf("Null child added to class %s\n", iter
->name
);
212 if (bytes_identical(iter
->name
, name
))
214 if (iter
->nextsib
!= NULL
)
215 { iter
= iter
->nextsib
;
219 iter
= struct_alloc(ir_class_t
);
220 iter
->nextsib
= class->nextchild
;
221 iter
->name
= name_alloc(name
);
222 return class->nextchild
= iter
;
225 /* Add a set to a class
226 Attempts to create a new root set in the specified class, returning
227 the set if it already exists
229 struct ir_set_t
* ir_class_addset
230 ( struct ir_class_t
* class,
233 { struct ir_set_t
* iter
;
234 if (class->root_set
== NULL
)
236 iter
= class->root_set
;
237 if (iter
->name
== NULL
)
238 eprintf("Null name pointer in class %p\n", iter
);
240 eprintf("Null set added to class %U\n", iter
->name
);
242 if (bytes_identical(iter
->name
, name
))
244 if (iter
->nextsib
!= NULL
)
245 { iter
= iter
->nextsib
;
249 iter
= struct_alloc(ir_set_t
);
250 iter
->nextsib
= class->root_set
;
251 iter
->name
= name_alloc(name
);
252 return class->root_set
= iter
;
255 /* Add a set to a set
256 Attempts to create a new subset of the specified set, returning the
257 child if it already exists
259 struct ir_set_t
* ir_set_addchild
260 ( struct ir_set_t
* set
,
263 { struct ir_set_t
* iter
;
264 if (set
->nextchild
== NULL
)
266 iter
= set
->nextchild
;
267 if (iter
->name
== NULL
)
268 eprintf("Null name pointer in set %p\n", iter
);
270 eprintf("Null child added to set %s\n", iter
->name
);
272 if (bytes_identical(iter
->name
, name
))
274 if (iter
->nextsib
!= NULL
)
275 { iter
= iter
->nextsib
;
279 iter
= struct_alloc(ir_set_t
);
280 iter
->nextsib
= set
->nextchild
;
281 iter
->name
= name_alloc(name
);
282 return set
->nextchild
= iter
;
285 /* Add a framebox to a set
286 Attempts to create a new framebox of the specified set, returning
287 the framebox if it already exists
290 struct ir_framebox_t
* ir_set_add_framebox
291 ( struct ir_set_t
* set
,
294 { struct ir_framebox_t
* iter
;
295 if (set
->frameboxes
== NULL
)
297 iter
= set
->frameboxes
;
299 if (bytes_identical(iter
->header
.data_name
, name
))
301 if (iter
->header
.nextsib
!= NULL
)
302 { 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
317 ( const uint8_t* stra
,
324 } while (ca
&& 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
,
396 eprintf("Null path in data %s\n", setdata
->header
.data_name
);
397 if (setdata
->header
.src_filename
!= NULL
)
398 wprintf("Path override: %s -> %s for setdata %s\n",
399 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
400 setdata
->header
.src_filename
= name_alloc(path
);
403 union ir_setdata_t
* ir_framesheet
404 ( const uint8_t* name
,
409 { return ir_framedata(FSDAT
, name
, d
, width
, height
); }
411 union ir_setdata_t
* ir_mapsheet
412 ( const uint8_t* name
,
417 { return ir_framedata(MSDAT
, name
, d
, width
, height
); }
420 union ir_setdata_t
* ir_framedata
427 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
429 eprintf("Null name in set allocation\n");
430 framedata
->header
.type
= type
;
431 framedata
->header
.data_name
= name_alloc(name
);
432 framedata
->frameinfo
.facing
= d
;
433 framedata
->frameinfo
.w
= width
;
434 framedata
->frameinfo
.h
= height
;
435 return (union ir_setdata_t
*) framedata
;
438 union ir_setdata_t
* ir_audio
439 ( const uint8_t* name
)
440 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
442 eprintf("Null audio\n");
443 audio
->header
.type
= ADAT
;
444 audio
->header
.data_name
= name_alloc(name
);
445 return (union ir_setdata_t
*) audio
;
449 /* Create classld that points to a class */
450 struct ir_classld_t
* ir_classld_from_class
451 ( struct ir_class_t
* class )
452 { struct ir_classld_t
* classld
;
454 eprintf("Null class in classld\n");
455 classld
= struct_alloc(ir_classld_t
);
456 classld
->root_class
= class;
460 struct ir_setld_t
* ir_setld_from_ref
462 { struct ir_setld_t
* setld
;
463 setld
= struct_alloc(ir_setld_t
);
468 struct ir_setld_t
* ir_setld_from_classld
469 ( struct ir_classld_t
* classld
,
472 { struct ir_setld_t
* setld
;
473 setld
= struct_alloc(ir_setld_t
);
474 setld
->namelist
= struct_alloc(ir_namelist_t
);
475 setld
->namelist_head
= setld
->namelist
;
476 setld
->namelist_head
->name
= name_alloc(name
);
477 setld
->classld
= classld
;
481 struct ir_setld_t
* ir_setld_addchild
482 ( struct ir_setld_t
* setld
,
485 { if (setld
->namelist
== NULL
)
486 { setld
->namelist
= struct_alloc(ir_namelist_t
);
487 setld
->namelist_head
= setld
->namelist
;
490 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
491 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
493 setld
->namelist_head
->name
= name_alloc(name
);
497 union ir_setdata_t
* ir_link
498 ( enum ltype link_type
,
499 struct ir_setld_t
* setld
,
502 { struct ir_link_t
* link
;
503 link
= struct_alloc(ir_link_t
);
504 link
->header
.type
= LDAT
;
505 link
->type
= link_type
;
506 link
->classld
= setld
->classld
;
508 if (link_type
!= OLINK
&& name
!= NULL
)
509 link
->header
.data_name
= name_alloc(name
);
510 return (union ir_setdata_t
*) link
;
517 { if (!bytes
) //valid behavior to attain current head
518 return datapages
.head
->header
.head
;
519 if (PL_HEADMEM(datapages
) < bytes
)
520 { datapages
.head
->header
.next
= (struct pagenode_t
*) calloc(datapages
.pagesize
,1);
521 if (datapages
.head
->header
.next
== NULL
)
522 eprintf("Memory allocation error \n");
523 datapages
.head
= datapages
.head
->header
.next
;
524 datapages
.head
->header
.head
= datapages
.head
->root
;
526 datapages
.head
->header
.head
+= bytes
;
527 return (void*) datapages
.head
->header
.head
- bytes
;
532 ( const uint8_t* name_src
)
533 { const uint8_t* iter
;
537 name
= (uint8_t*)namepages
.head
->header
.head
;
539 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& *iter
!= '_' && head_mem
; head_mem
--)
540 *(namepages
.head
->header
.head
)++ = *iter
++;
541 if (head_mem
== 0) //not enough room
542 { namepages
.head
->header
.next
= (struct pagenode_t
*) calloc(namepages
.pagesize
,1);
543 if (namepages
.head
->header
.next
== NULL
)
544 eprintf("Memory allocation error\n");
545 namepages
.head
= namepages
.head
->header
.next
;
546 namepages
.head
->header
.head
= namepages
.head
->root
;
549 *(namepages
.head
->header
.head
)++ = '\0';