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);
31 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*, uint8_t*);
33 void ir_free_pages(struct pagenode_t
*);
35 int bytes_identical(uint8_t*,uint8_t*);
37 void* stack_alloc(size_t);
38 /* Memory allocator */
40 struct pagenode_t
* next
;
43 }* pagenode_root
, * pagenode_head
;
44 #define PN_ALLOCSIZE (sys_pagesize)
45 #define PN_HEADERSIZE() (sizeof(struct pagenode_t*) + sizeof(char*))
46 #define PN_MEMSIZE() (PN_ALLOCSIZE - PN_HEADERSIZE())
47 #define PN_HEADSIZE() (pagenode_head->head - pagenode_head->root)
48 #define PN_HEADSPACE() (PN_MEMSIZE() - PN_HEADSIZE())
49 /* Enumerated types */
50 enum dtype
{ FSDAT
, MSDAT
, ADAT
, LDAT
, FBDAT
};
51 enum ltype
{ OLINK
, MLINK
, VLINK
, ALINK
};
53 struct ir_setdata_header_t
55 uint8_t* src_filename
, * data_name
;
56 union ir_setdata_t
* nextsib
;
59 { int facing
, w
, h
; };
61 { struct ir_setdata_header_t header
;
62 struct ir_frameinfo_t frameinfo
;
65 { struct ir_setdata_header_t header
;
66 struct ir_framedata_t framesheets
[FACING_MAX
];
67 struct ir_framedata_t mapsheets
[FACING_MAX
];
70 { struct ir_setdat_header_t header
;
73 { struct ir_setdat_header_t header
;
74 struct ir_set_t
* src
, * trg
;
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 framebox_t
* frameboxes
;
96 struct simplex_t
* audio
;
99 /* Function-Like Macros */
100 #define do_warn() do { \
102 #define wprint(str) do { \
103 fprintf(stderr, str); \
106 #define wprintf(fmt,...) do { \
107 fprintf(stderr, fmt, __VA_ARGS__); \
110 #define do_error() do { \
113 #define eprint(str) do { \
114 fprintf(stderr, str); \
117 #define eprintf(fmt,...) do { \
118 fprintf(stderr, fmt, __VA_ARGS__); \
121 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
125 struct ir_class_t root_class
= { .name
= "." };
130 { pagenode_root
= calloc(struct pagenode_t
*) calloc(PN_ALLOCSIZE
);
131 if (pagenode_root
== NULL
)
133 pagenode_root
->head
= pagenode_root
->root
;
134 pagenode_head
= pagenode_root
;
139 Recursively clean pagenode linked list
143 { ir_free_pages(pagenode_root
); }
147 ( struct pagenode_t
* pagenode
)
148 { if (pagenode
->next
!= NULL
)
149 ir_free_pages(pagenode
->next
);
165 /* Return a pointer to the root class */
166 struct ir_class_t
* ir_class_root
168 { return &root_class
; }
170 /* Add a subclass to a class
171 Attempts to create a new subclass in the provided class, returning
172 the class if it already exists
174 struct ir_class_t
* ir_class_addchild
175 ( struct ir_class_t
* class,
178 { struct ir_class_t
* iter
;
179 if (class->nextchild
== NULL
)
180 return class->nextchild
= struct_alloc(ir_class_t
);
181 iter
= class->nextchild
;
183 if (bytes_identical(iter
->name
, name
))
185 if (iter
->nextsib
!= NULL
)
186 { iter
= iter
->nextsib
;
189 return iter
->nextsib
= struct_alloc(ir_class_t
);
192 /* Add a set to a class
193 Attempts to create a new root set in the specified class, returning
194 the set if it already exists
196 struct ir_set_t
* ir_class_addset
197 ( struct ir_class_t
* class,
200 { struct ir_set_t
* iter
;
201 if (class->root_set
== NULL
)
202 return class->root_set
= struct_alloc(ir_set_t
);
203 iter
= class->root_set
;
205 if (bytes_identical(iter
->name
, name
))
207 if (iter
->nextsib
!= NULL
)
208 { iter
= iter
->nextsib
;
211 return iter
->nextsib
= struct_alloc(ir_set_t
);
214 /* Add a set to a set
215 Attempts to create a new subset of the specified set, returning the
216 child if it already exists
218 struct ir_set_t
* ir_set_addchild
219 ( struct ir_set_t
* set
,
222 { struct ir_set_t
* iter
;
223 if (set
->nextchild
== NULL
)
224 return set
->nextchild
= struct_alloc(ir_set_t
);
225 iter
= set
->nextchild
;
227 if (bytes_identical(iter
->name
, name
))
229 if (iter
->nextsib
!= NULL
)
230 { iter
= iter
->nextsib
;
233 return iter
->nextsib
= struct_alloc(ir_set_t
);
236 /* Add a framebox to a set
237 Attempts to create a new framebox of the specified set, returning
238 the framebox if it already exists
241 struct ir_framebox_t
* ir_set_add_framebox
242 ( struct ir_set_t
* set
,
245 { struct ir_framebox_t
* iter
;
246 if (set
->frameboxes
== NULL
)
247 return set
->frameboxes
= struct_alloc(ir_framebox_t
);
248 iter
= set
->frameboxes
;
250 if (bytes_identical(iter
->header
.name
, name
))
252 if (iter
->header
.nextsib
!= NULL
)
253 { iter
= iter
->header
.nextsib
;
256 return iter
->header
.nextsib
= struct_alloc(ir_framebox_t
);
259 /* Match two null-terminated bytestrings
260 Return 1 if the two bytestrings are identical, else 0
267 { while (*stra
&& *strb
)
268 if (*stra
++ != *strb
++)
270 return *stra
== *strb
;
273 /* Assign Setdata to Set
276 void ir_set_assign_data
277 ( struct ir_set_t
* set
,
278 union ir_setdata_t
* setdata
280 { struct ir_framebox_t
* framebox
;
281 struct ir_simplex_t
* simplex
;
282 struct ir_link_t
* link
;
283 switch (setdata
->header
.type
)
285 framebox
= ir_set_add_framebox(set
, setdata
->header
.name
);
286 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] != NULL
)
287 wprintf("Duplicate framesheet [%i] %s\n",
288 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
289 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
292 framebox
= ir_set_add_framebox(set
, setdata
->header
.name
);
293 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] != NULL
)
294 wprintf("Duplicate mapsheet [%i] %s\n",
295 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
296 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
299 if (set
->audio
== NULL
)
300 { set
->audio
= &setdata
->audio
;
303 simplex
= set
->audio
;
304 while (simplex
->header
.nextsib
!= NULL
;)
305 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
306 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
307 *simplex
= setdata
->audio
;
311 simplex
= simplex
->header
.nextsib
;
312 simplex
->header
.nextsib
= &setdata
->audio
;
315 if (set
->links
== NULL
)
316 { set
->links
= &setdata
->link
;
320 while (link
->header
.nextsib
!= NULL
)
321 link
= link
->header
.nextsib
;
322 link
->header
.nextsib
= &setdata
->link
;
325 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
330 void ir_set_assign_ref
335 wprintf("Ref override: 0x%x -> 0x%x for set %s\n",
336 set
->ref
, ref
, set
->name
);
338 //TODO: reflist_add(set);
341 void ir_data_assign_path
342 ( union ir_setdata_t
* setdata
,
345 { if (set
->header
.src_filename
)
346 wprintf("Path override: %s -> %s for set %s\n",
347 set
->header
.src_filename
, path
, set
->name
);
348 set
->header
.src_filename
= path
;
349 //TODO: internal strdup, not assign (= path;)
353 //TODO: Macro ir_framsheet and mapsheet?
354 union ir_setdata_t
* ir_framesheet
360 { struct ir_framedata_t
* framesheet
= struct_alloc(ir_framedata_t
);
361 framesheet
->header
->type
= FSDAT
;
362 framesheet
->header
.data_name
= name
;
363 framesheet
->frameinfo
.facing
= d
;
364 framesheet
->frameinfo
.w
= width
;
365 framesheet
->frameinfo
.h
= height
;
366 return (union ir_setdata_t
*) framesheet
;
369 union ir_setdata_t
* ir_mapsheet
375 { struct ir_framedata_t
* mapsheet
= struct_alloc(ir_framedata_t
);
376 mapsheet
->header
.type
= MSDAT
;
377 mapsheet
->header
.data_name
= name
;
378 mapsheet
->frameinfo
.facing
= d
;
379 mapsheet
->frameinfo
.w
= width
;
380 mapsheet
->frameinfo
.h
= height
;
381 return (union ir_setdata_t
*) mapsheet
;
384 union ir_setdata_t
* ir_audio
386 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
387 audio
->header
.type
= ADAT
;
388 audio
->header
.data_name
= name
;
389 return (union ir_setdata_t
*) audio
;
393 void* stack_alloc(size_t bytes
)
395 { wprint("Attempting to allocate 0 bytes in stack_alloc");
396 return pagenode_head
->head
;
398 if (PN_HEADSPACE() < bytes
)
399 { pagenode_head
->next
= (struct pagenode_t
*) calloc(PN_ALLOCSIZE
);
400 pagenode_head
= pagenode_head
->next
;
401 pagenode_head
->head
= pagenode_head
->root
;
403 pagenode_head
->head
+= bytes
;
404 return (void*) pagenode_head
->head
- bytes
;