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);
30 struct ir_framebox_t
* ir_set_add_framebox(struct ir_set_t
*, uint8_t*);
32 void ir_free_pages(struct pagenode_t
*);
34 int bytes_identical(uint8_t*,uint8_t*);
36 void* stack_alloc(size_t);
37 /* Memory allocator */
39 struct pagenode_t
* next
;
42 }* pagenode_root
, * pagenode_head
;
43 #define PN_ALLOCSIZE (sys_pagesize)
44 #define PN_HEADERSIZE() (sizeof(struct pagenode_t*) + sizeof(char*))
45 #define PN_MEMSIZE() (PN_ALLOCSIZE - PN_HEADERSIZE())
46 #define PN_HEADSIZE() (pagenode_head->head - pagenode_head->root)
47 #define PN_HEADSPACE() (PN_MEMSIZE() - PN_HEADSIZE())
48 /* Enumerated types */
49 enum dtype
{ FSDAT
, MSDAT
, ADAT
, LDAT
, FBDAT
};
50 enum ltype
{ OLINK
, MLINK
, VLINK
, ALINK
};
52 struct ir_setdata_header_t
54 uint8_t* src_filename
, * data_name
;
55 union ir_setdata_t
* nextsib
;
58 { int facing
, w
, h
; };
60 { struct ir_setdata_header_t header
;
61 struct ir_frameinfo_t frameinfo
;
64 { struct ir_setdata_header_t header
;
65 struct ir_framedata_t framesheets
[FACING_MAX
];
66 struct ir_framedata_t mapsheets
[FACING_MAX
];
69 { struct ir_setdata_header_t header
; };
71 { struct ir_setdata_header_t header
;
72 struct ir_set_t
* src
, * trg
;
76 { struct ir_setdata_header_t header
;
77 struct ir_framebox_t framebox
;
78 struct ir_framedata_t framesheet
;
79 struct ir_framedata_t mapsheet
;
80 struct ir_simplex_t audio
;
81 struct ir_link_t link
;
84 { struct ir_class_t
* nextchild
, * nextsib
;
85 struct ir_set_t
* root_set
;
89 { struct ir_set_t
* nextchild
, * nextsib
;
90 struct ir_class_t
* class;
93 struct ir_framebox_t
* frameboxes
;
94 struct ir_simplex_t
* audio
;
95 struct ir_link_t
* links
;
97 /* Function-Like Macros */
98 #define do_warn() do { \
100 #define wprint(str) do { \
101 fprintf(stderr, str); \
104 #define wprintf(fmt,...) do { \
105 fprintf(stderr, fmt, __VA_ARGS__); \
108 #define do_error() do { \
111 #define eprint(str) do { \
112 fprintf(stderr, str); \
115 #define eprintf(fmt,...) do { \
116 fprintf(stderr, fmt, __VA_ARGS__); \
119 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
122 struct ir_class_t root_class
= { .name
= (uint8_t*)"." };
127 { pagenode_root
= (struct pagenode_t
*) calloc((size_t)PN_ALLOCSIZE
,1);
128 if (pagenode_root
== NULL
)
130 pagenode_root
->head
= pagenode_root
->root
;
131 pagenode_head
= pagenode_root
;
136 Recursively clean pagenode linked list
140 { ir_free_pages(pagenode_root
); }
144 ( struct pagenode_t
* pagenode
)
145 { if (pagenode
->next
!= NULL
)
146 ir_free_pages(pagenode
->next
);
162 /* Return a pointer to the root class */
163 struct ir_class_t
* ir_class_root
165 { return &root_class
; }
167 /* Add a subclass to a class
168 Attempts to create a new subclass in the provided class, returning
169 the class if it already exists
171 struct ir_class_t
* ir_class_addchild
172 ( struct ir_class_t
* class,
175 { struct ir_class_t
* iter
;
176 if (class->nextchild
== NULL
)
177 return class->nextchild
= struct_alloc(ir_class_t
);
178 iter
= class->nextchild
;
180 if (bytes_identical(iter
->name
, name
))
182 if (iter
->nextsib
!= NULL
)
183 { iter
= iter
->nextsib
;
186 return iter
->nextsib
= struct_alloc(ir_class_t
);
189 /* Add a set to a class
190 Attempts to create a new root set in the specified class, returning
191 the set if it already exists
193 struct ir_set_t
* ir_class_addset
194 ( struct ir_class_t
* class,
197 { struct ir_set_t
* iter
;
198 if (class->root_set
== NULL
)
199 return class->root_set
= struct_alloc(ir_set_t
);
200 iter
= class->root_set
;
202 if (bytes_identical(iter
->name
, name
))
204 if (iter
->nextsib
!= NULL
)
205 { iter
= iter
->nextsib
;
208 return iter
->nextsib
= struct_alloc(ir_set_t
);
211 /* Add a set to a set
212 Attempts to create a new subset of the specified set, returning the
213 child if it already exists
215 struct ir_set_t
* ir_set_addchild
216 ( struct ir_set_t
* set
,
219 { struct ir_set_t
* iter
;
220 if (set
->nextchild
== NULL
)
221 return set
->nextchild
= struct_alloc(ir_set_t
);
222 iter
= set
->nextchild
;
224 if (bytes_identical(iter
->name
, name
))
226 if (iter
->nextsib
!= NULL
)
227 { iter
= iter
->nextsib
;
230 return iter
->nextsib
= struct_alloc(ir_set_t
);
233 /* Add a framebox to a set
234 Attempts to create a new framebox of the specified set, returning
235 the framebox if it already exists
238 struct ir_framebox_t
* ir_set_add_framebox
239 ( struct ir_set_t
* set
,
242 { struct ir_framebox_t
* iter
;
243 if (set
->frameboxes
== NULL
)
244 return set
->frameboxes
= struct_alloc(ir_framebox_t
);
245 iter
= set
->frameboxes
;
247 if (bytes_identical(iter
->header
.data_name
, name
))
249 if (iter
->header
.nextsib
!= NULL
)
250 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
253 iter
->header
.nextsib
= (union ir_setdata_t
*) struct_alloc(ir_framebox_t
);
254 return (struct ir_framebox_t
*) iter
->header
.nextsib
;
257 /* Match two null-terminated bytestrings
258 Return 1 if the two bytestrings are identical, else 0
265 { while (*stra
&& *strb
)
266 if (*stra
++ != *strb
++)
268 return *stra
== *strb
;
271 /* Assign Setdata to Set
274 void ir_set_assign_data
275 ( struct ir_set_t
* set
,
276 union ir_setdata_t
* setdata
278 { struct ir_framebox_t
* framebox
;
279 struct ir_simplex_t
* simplex
;
280 struct ir_link_t
* link
;
281 switch (setdata
->header
.type
)
283 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
284 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
285 wprintf("Duplicate framesheet [%i] %s\n",
286 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
287 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
290 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
291 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
292 wprintf("Duplicate mapsheet [%i] %s\n",
293 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
294 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
297 if (set
->audio
== NULL
)
298 { set
->audio
= (struct ir_simplex_t
*) setdata
;
301 simplex
= set
->audio
;
302 while (simplex
->header
.nextsib
!= NULL
)
303 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
304 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
305 *simplex
= setdata
->audio
;
306 //setdata->audio is now a pointer to redundant, unused memory.
310 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
311 simplex
->header
.nextsib
= setdata
;
314 if (set
->links
== NULL
)
315 { set
->links
= (struct ir_link_t
*) setdata
;
319 while (link
->header
.nextsib
!= NULL
)
320 link
= (struct ir_link_t
*) link
->header
.nextsib
;
321 link
->header
.nextsib
= (struct ir_link_t
*) setdata
;
324 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
329 void ir_set_assign_ref
330 ( struct ir_set_t
* set
,
334 wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",
335 (long unsigned) set
->ref
, (long unsigned) ref
, set
->name
);
337 //TODO: reflist_add(set);
340 void ir_data_assign_path
341 ( union ir_setdata_t
* setdata
,
344 { setdata
->header
.src_filename
= path
;
345 //TODO: internal strdup, not assign (= path;)
349 //TODO: Macro ir_framsheet and mapsheet?
350 union ir_setdata_t
* ir_framesheet
356 { struct ir_framedata_t
* framesheet
= struct_alloc(ir_framedata_t
);
357 framesheet
->header
.type
= FSDAT
;
358 framesheet
->header
.data_name
= name
;
359 framesheet
->frameinfo
.facing
= d
;
360 framesheet
->frameinfo
.w
= width
;
361 framesheet
->frameinfo
.h
= height
;
362 return (union ir_setdata_t
*) framesheet
;
365 union ir_setdata_t
* ir_mapsheet
371 { struct ir_framedata_t
* mapsheet
= struct_alloc(ir_framedata_t
);
372 mapsheet
->header
.type
= MSDAT
;
373 mapsheet
->header
.data_name
= name
;
374 mapsheet
->frameinfo
.facing
= d
;
375 mapsheet
->frameinfo
.w
= width
;
376 mapsheet
->frameinfo
.h
= height
;
377 return (union ir_setdata_t
*) mapsheet
;
380 union ir_setdata_t
* ir_audio
382 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
383 audio
->header
.type
= ADAT
;
384 audio
->header
.data_name
= name
;
385 return (union ir_setdata_t
*) audio
;
389 void* stack_alloc(size_t bytes
)
391 { wprint("Attempting to allocate 0 bytes in stack_alloc");
392 return pagenode_head
->head
;
394 if (PN_HEADSPACE() < bytes
)
395 { pagenode_head
->next
= (struct pagenode_t
*) calloc(PN_ALLOCSIZE
,1);
396 pagenode_head
= pagenode_head
->next
;
397 pagenode_head
->head
= pagenode_head
->root
;
399 pagenode_head
->head
+= bytes
;
400 return (void*) pagenode_head
->head
- bytes
;