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 */
26 enum dtype
{ FSDAT
, MSDAT
, ADAT
, LDAT
, FBDAT
};
28 struct pagenode_header_t
{
29 struct pagenode_t
* next
;
33 struct pagenode_header_t header
;
37 struct pagenode_t
* root
, * head
;
42 { struct ir_namelist_t
* nextsib
;
46 { struct ir_class_t
* root_class
;
47 struct ir_namelist_t
* namelist
, * namelist_head
;
50 { struct ir_classld_t
* classld
;
52 struct ir_namelist_t
* namelist
, * namelist_head
;
55 struct ir_setdata_header_t
57 uint8_t* src_filename
, * data_name
;
58 union ir_setdata_t
* nextsib
;
61 { int facing
, w
, h
; };
63 { struct ir_setdata_header_t header
;
64 struct ir_frameinfo_t frameinfo
;
67 { struct ir_setdata_header_t header
;
68 struct ir_framedata_t framesheets
[FACING_MAX
];
69 struct ir_framedata_t mapsheets
[FACING_MAX
];
71 struct ir_simplex_t
{ struct ir_setdata_header_t header
; };
73 { struct ir_setdata_header_t header
;
74 struct ir_classld_t
* classld
;
75 struct ir_setld_t
* setld
;
79 { struct ir_setdata_header_t header
;
80 struct ir_framebox_t framebox
;
81 struct ir_framedata_t framesheet
;
82 struct ir_framedata_t mapsheet
;
83 struct ir_simplex_t audio
;
84 struct ir_link_t link
;
87 { struct ir_class_t
* nextchild
, * nextsib
;
88 struct ir_set_t
* root_set
;
92 { struct ir_set_t
* nextchild
, * nextsib
;
93 struct ir_class_t
* class;
96 struct ir_framebox_t
* frameboxes
;
97 struct ir_simplex_t
* audio
;
98 struct ir_link_t
* links
;
102 int init_pagelist(struct pagelist_t
*,size_t);
104 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*,const uint8_t*);
106 void ir_free_pagenodes(struct pagenode_t
*);
108 int bytes_identical(const uint8_t*,const uint8_t*);
110 void* stack_alloc(size_t);
112 uint8_t* name_alloc(const uint8_t*);
114 union ir_setdata_t
* ir_framedata (enum dtype
,const uint8_t*,apc_facing
,int,int);
115 /* Function-Like Macros */
116 #define do_warn() do { \
118 #define wprint(str) do { \
119 fprintf(stderr, str); \
122 #define wprintf(fmt,...) do { \
123 fprintf(stderr, fmt, __VA_ARGS__); \
126 #define do_error() do { \
129 #define eprint(str) do { \
130 fprintf(stderr, str); \
133 #define eprintf(fmt,...) do { \
134 fprintf(stderr, fmt, __VA_ARGS__); \
137 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
138 #define DATA_PAGESIZE (sys_pagesize)
139 #define NAME_PAGESIZE (APC_NAME_MAX * 1024)
140 #define PL_HEADERSIZE (sizeof(struct pagenode_header_t))
141 #define PL_HEADSIZE(_PL) (_PL.head->header.head - _PL.head->root)
142 #define PL_HEADMEM(_PL) (_PL.pagesize - PL_HEADERSIZE - PL_HEADSIZE(_PL))
147 struct pagelist_t datapages
, namepages
;
149 struct ir_class_t root_class
= { .name
= (uint8_t*)"." };
154 { if (init_pagelist(&datapages
, (size_t)DATA_PAGESIZE
))
155 eprint("Memory allocation error\n");
156 if (init_pagelist(&namepages
, (size_t)NAME_PAGESIZE
))
157 eprint("Memory allocation error\n");
163 ( struct pagelist_t
* pl
,
166 { pl
->pagesize
= size
;
167 pl
->root
= (struct pagenode_t
*) calloc(size
,1);
168 if (pl
->root
== NULL
)
170 pl
->root
->header
.head
= pl
->root
->root
;
176 Recursively clean pagenode linked list
180 { ir_free_pagenodes(datapages
.root
);
181 ir_free_pagenodes(namepages
.root
);
185 void ir_free_pagenodes
186 ( struct pagenode_t
* pagenode
)
187 { if (pagenode
->header
.next
!= NULL
)
188 ir_free_pagenodes(pagenode
->header
.next
);
204 /* Return the class's name string */
205 uint8_t* ir_class_name
206 ( struct ir_class_t
* class )
207 { return class->name
; }
209 /* Return a pointer to the root class */
210 struct ir_class_t
* ir_class_root
212 { return &root_class
; }
214 /* Add a subclass to a class
215 Attempts to create a new subclass in the provided class, returning
216 the class if it already exists
218 struct ir_class_t
* ir_class_addchild
219 ( struct ir_class_t
* class,
222 { struct ir_class_t
* iter
;
223 printf("Class %s, addchild %s\n", class->name
, name
);
224 if (class->nextchild
== NULL
)
226 iter
= class->nextchild
;
227 if (iter
->name
== NULL
)
228 eprintf("Null name pointer in class %p\n", iter
);
230 eprintf("Null child added to class %s\n", iter
->name
);
232 if (bytes_identical(iter
->name
, name
))
234 if (iter
->nextsib
!= NULL
)
235 { iter
= iter
->nextsib
;
239 iter
= struct_alloc(ir_class_t
);
240 iter
->nextsib
= class->nextchild
;
241 iter
->name
= name_alloc(name
);
242 return class->nextchild
= iter
;
245 /* Add a set to a class
246 Attempts to create a new root set in the specified class, returning
247 the set if it already exists
249 struct ir_set_t
* ir_class_addset
250 ( struct ir_class_t
* class,
253 { struct ir_set_t
* iter
;
254 printf("Class %s, addset %s\n", class->name
, name
);
255 if (class->root_set
== NULL
)
257 iter
= class->root_set
;
258 if (iter
->name
== NULL
)
259 eprintf("Null name pointer in class %p\n", iter
);
261 eprintf("Null set added to class %s\n", iter
->name
);
263 if (bytes_identical(iter
->name
, name
))
265 if (iter
->nextsib
!= NULL
)
266 { iter
= iter
->nextsib
;
270 iter
= struct_alloc(ir_set_t
);
271 iter
->nextsib
= class->root_set
;
272 iter
->name
= name_alloc(name
);
273 return class->root_set
= iter
;
276 /* Add a set to a set
277 Attempts to create a new subset of the specified set, returning the
278 child if it already exists
280 struct ir_set_t
* ir_set_addchild
281 ( struct ir_set_t
* set
,
284 { struct ir_set_t
* iter
;
285 printf("Set %s, addchild %s\n", set
->name
, name
);
286 if (set
->nextchild
== NULL
)
288 iter
= set
->nextchild
;
289 if (iter
->name
== NULL
)
290 eprintf("Null name pointer in set %p\n", iter
);
292 eprintf("Null child added to set %s\n", iter
->name
);
294 if (bytes_identical(iter
->name
, name
))
296 if (iter
->nextsib
!= NULL
)
297 { iter
= iter
->nextsib
;
301 iter
= struct_alloc(ir_set_t
);
302 iter
->nextsib
= set
->nextchild
;
303 iter
->name
= name_alloc(name
);
304 return set
->nextchild
= iter
;
307 /* Add a framebox to a set
308 Attempts to create a new framebox of the specified set, returning
309 the framebox if it already exists
312 struct ir_framebox_t
* ir_set_add_framebox
313 ( struct ir_set_t
* set
,
316 { struct ir_framebox_t
* iter
;
317 if (set
->frameboxes
== NULL
)
319 iter
= set
->frameboxes
;
321 if (bytes_identical(iter
->header
.data_name
, name
))
323 if (iter
->header
.nextsib
!= NULL
)
324 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
328 iter
= struct_alloc(ir_framebox_t
);
329 iter
->header
.nextsib
= (union ir_setdata_t
*) set
->frameboxes
;
330 iter
->header
.data_name
= name_alloc(name
);
331 return set
->frameboxes
= iter
;
334 /* Match two null-terminated bytestrings
335 Return 1 if the two bytestrings are identical, else 0
339 ( const uint8_t* stra
,
346 } while (ca
&& ca
!= '_' && ca
== cb
);
350 /* Assign Setdata to Set
353 void ir_set_assign_data
354 ( struct ir_set_t
* set
,
355 union ir_setdata_t
* setdata
357 { struct ir_framebox_t
* framebox
;
358 struct ir_simplex_t
* simplex
;
359 switch (setdata
->header
.type
)
361 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
362 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
363 wprintf("Duplicate framesheet [%i] %s\n",
364 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
365 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
368 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
369 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
370 wprintf("Duplicate mapsheet [%i] %s\n",
371 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
372 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
375 if (set
->audio
== NULL
)
376 { set
->audio
= (struct ir_simplex_t
*) setdata
;
379 simplex
= set
->audio
;
380 while (simplex
->header
.nextsib
!= NULL
)
381 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
382 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
383 *simplex
= setdata
->audio
;
384 //setdata is now a pointer to redundant, unused memory.
388 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
389 setdata
->audio
.header
.nextsib
= (union ir_setdata_t
*) set
->audio
;
390 set
->audio
= (struct ir_simplex_t
*) setdata
;
393 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
394 set
->links
= (struct ir_link_t
*) setdata
;
397 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
402 void ir_set_assign_ref
403 ( struct ir_set_t
* set
,
407 wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",
408 (long unsigned) set
->ref
, (long unsigned) ref
, set
->name
);
410 //TODO: reflist_add(set);
413 void ir_data_assign_path
414 ( union ir_setdata_t
* setdata
,
418 eprintf("Null path in data %s\n", setdata
->header
.data_name
);
419 if (setdata
->header
.src_filename
!= NULL
)
420 wprintf("Path override: %s -> %s for setdata %s\n",
421 setdata
->header
.src_filename
, path
, setdata
->header
.data_name
);
422 setdata
->header
.src_filename
= name_alloc(path
);
425 union ir_setdata_t
* ir_framesheet
426 ( const uint8_t* name
,
431 { return ir_framedata(FSDAT
, name
, d
, width
, height
); }
433 union ir_setdata_t
* ir_mapsheet
434 ( const uint8_t* name
,
439 { return ir_framedata(MSDAT
, name
, d
, width
, height
); }
442 union ir_setdata_t
* ir_framedata
449 { struct ir_framedata_t
* framedata
= struct_alloc(ir_framedata_t
);
451 eprint("Null name in set allocation\n");
452 framedata
->header
.type
= type
;
453 framedata
->header
.data_name
= name_alloc(name
);
454 framedata
->frameinfo
.facing
= d
;
455 framedata
->frameinfo
.w
= width
;
456 framedata
->frameinfo
.h
= height
;
457 return (union ir_setdata_t
*) framedata
;
460 union ir_setdata_t
* ir_audio
461 ( const uint8_t* name
)
462 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
464 eprint("Null audio\n");
465 audio
->header
.type
= ADAT
;
466 audio
->header
.data_name
= name_alloc(name
);
467 return (union ir_setdata_t
*) audio
;
471 /* Create classld that points to a class */
472 struct ir_classld_t
* ir_classld_from_class
473 ( struct ir_class_t
* class )
474 { struct ir_classld_t
* classld
;
476 eprint("Null class in classld\n");
477 classld
= struct_alloc(ir_classld_t
);
478 classld
->root_class
= class;
482 struct ir_setld_t
* ir_setld_from_ref
484 { struct ir_setld_t
* setld
;
485 setld
= struct_alloc(ir_setld_t
);
490 struct ir_setld_t
* ir_setld_from_classld
491 ( struct ir_classld_t
* classld
,
494 { struct ir_setld_t
* setld
;
495 setld
= struct_alloc(ir_setld_t
);
496 setld
->namelist
= struct_alloc(ir_namelist_t
);
497 setld
->namelist_head
= setld
->namelist
;
498 setld
->namelist_head
->name
= name_alloc(name
);
499 setld
->classld
= classld
;
503 struct ir_setld_t
* ir_setld_addchild
504 ( struct ir_setld_t
* setld
,
507 { if (setld
->namelist
== NULL
)
508 { setld
->namelist
= struct_alloc(ir_namelist_t
);
509 setld
->namelist_head
= setld
->namelist
;
512 { setld
->namelist_head
->nextsib
= struct_alloc(ir_namelist_t
);
513 setld
->namelist_head
= setld
->namelist_head
->nextsib
;
515 setld
->namelist_head
->name
= name_alloc(name
);
519 union ir_setdata_t
* ir_link
520 ( enum ltype link_type
,
521 struct ir_setld_t
* setld
,
524 { struct ir_link_t
* link
;
525 link
= struct_alloc(ir_link_t
);
526 link
->header
.type
= LDAT
;
527 link
->type
= link_type
;
528 link
->classld
= setld
->classld
;
530 if (link_type
!= OLINK
&& name
!= NULL
)
531 link
->header
.data_name
= name_alloc(name
);
532 return (union ir_setdata_t
*) link
;
539 { if (!bytes
) //valid behavior to attain current head
540 return datapages
.head
->header
.head
;
541 if (PL_HEADMEM(datapages
) < bytes
)
542 { datapages
.head
->header
.next
= (struct pagenode_t
*) calloc(datapages
.pagesize
,1);
543 if (datapages
.head
->header
.next
== NULL
)
544 eprint("Memory allocation error \n");
545 datapages
.head
= datapages
.head
->header
.next
;
546 datapages
.head
->header
.head
= datapages
.head
->root
;
548 datapages
.head
->header
.head
+= bytes
;
549 return (void*) datapages
.head
->header
.head
- bytes
;
554 ( const uint8_t* name_src
)
555 { const uint8_t* iter
;
559 name
= (uint8_t*)namepages
.head
->header
.head
;
561 for (head_mem
= PL_HEADMEM(namepages
); *iter
&& *iter
!= '_' && head_mem
; head_mem
--)
562 *(namepages
.head
->header
.head
)++ = *iter
++;
563 if (head_mem
== 0) //not enough room
564 { namepages
.head
->header
.next
= (struct pagenode_t
*) calloc(namepages
.pagesize
,1);
565 if (namepages
.head
->header
.next
== NULL
)
566 eprint("Memory allocation error\n");
567 namepages
.head
= namepages
.head
->header
.next
;
568 namepages
.head
->header
.head
= namepages
.head
->root
;
571 *(namepages
.head
->header
.head
)++ = '\0';