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
};
54 { struct ir_namelist_t
* nextsib
;
58 { struct ir_class_t
* root_class
;
59 struct ir_namelist_t
* namelist
;
62 { struct classld_t
* classld
;
64 struct ir_namelist_t
* namelist
;
67 struct ir_setdata_header_t
69 uint8_t* src_filename
, * data_name
;
70 union ir_setdata_t
* nextsib
;
73 { int facing
, w
, h
; };
75 { struct ir_setdata_header_t header
;
76 struct ir_frameinfo_t frameinfo
;
79 { struct ir_setdata_header_t header
;
80 struct ir_framedata_t framesheets
[FACING_MAX
];
81 struct ir_framedata_t mapsheets
[FACING_MAX
];
84 { struct ir_setdata_header_t header
; };
86 { struct ir_setdata_header_t header
;
87 struct ir_classld_t
* classld
;
88 struct ir_setld_t
* setld
;
92 { struct ir_setdata_header_t header
;
93 struct ir_framebox_t framebox
;
94 struct ir_framedata_t framesheet
;
95 struct ir_framedata_t mapsheet
;
96 struct ir_simplex_t audio
;
97 struct ir_link_t link
;
100 { struct ir_class_t
* nextchild
, * nextsib
;
101 struct ir_set_t
* root_set
;
105 { struct ir_set_t
* nextchild
, * nextsib
;
106 struct ir_class_t
* class;
109 struct ir_framebox_t
* frameboxes
;
110 struct ir_simplex_t
* audio
;
111 struct ir_link_t
* links
;
113 /* Function-Like Macros */
114 #define do_warn() do { \
116 #define wprint(str) do { \
117 fprintf(stderr, str); \
120 #define wprintf(fmt,...) do { \
121 fprintf(stderr, fmt, __VA_ARGS__); \
124 #define do_error() do { \
127 #define eprint(str) do { \
128 fprintf(stderr, str); \
131 #define eprintf(fmt,...) do { \
132 fprintf(stderr, fmt, __VA_ARGS__); \
135 #define struct_alloc(_T) ((struct _T*) stack_alloc(sizeof(struct _T)))
138 struct ir_class_t root_class
= { .name
= (uint8_t*)"." };
143 { pagenode_root
= (struct pagenode_t
*) calloc((size_t)PN_ALLOCSIZE
,1);
144 if (pagenode_root
== NULL
)
146 pagenode_root
->head
= pagenode_root
->root
;
147 pagenode_head
= pagenode_root
;
152 Recursively clean pagenode linked list
156 { ir_free_pages(pagenode_root
); }
160 ( struct pagenode_t
* pagenode
)
161 { if (pagenode
->next
!= NULL
)
162 ir_free_pages(pagenode
->next
);
178 /* Return a pointer to the root class */
179 struct ir_class_t
* ir_class_root
181 { return &root_class
; }
183 /* Add a subclass to a class
184 Attempts to create a new subclass in the provided class, returning
185 the class if it already exists
187 struct ir_class_t
* ir_class_addchild
188 ( struct ir_class_t
* class,
191 { struct ir_class_t
* iter
;
192 if (class->nextchild
== NULL
)
193 return class->nextchild
= struct_alloc(ir_class_t
);
194 iter
= class->nextchild
;
196 if (bytes_identical(iter
->name
, name
))
198 if (iter
->nextsib
!= NULL
)
199 { iter
= iter
->nextsib
;
202 iter
= struct_alloc(ir_class_t
);
203 iter
->nextsib
= class->nextchild
;
204 return class->nextchild
= iter
;
207 /* Add a set to a class
208 Attempts to create a new root set in the specified class, returning
209 the set if it already exists
211 struct ir_set_t
* ir_class_addset
212 ( struct ir_class_t
* class,
215 { struct ir_set_t
* iter
;
216 if (class->root_set
== NULL
)
217 return class->root_set
= struct_alloc(ir_set_t
);
218 iter
= class->root_set
;
220 if (bytes_identical(iter
->name
, name
))
222 if (iter
->nextsib
!= NULL
)
223 { iter
= iter
->nextsib
;
226 iter
= struct_alloc(ir_set_t
);
227 iter
->nextsib
= class->root_set
;
228 return class->root_set
= iter
;
231 /* Add a set to a set
232 Attempts to create a new subset of the specified set, returning the
233 child if it already exists
235 struct ir_set_t
* ir_set_addchild
236 ( struct ir_set_t
* set
,
239 { struct ir_set_t
* iter
;
240 if (set
->nextchild
== NULL
)
241 return set
->nextchild
= struct_alloc(ir_set_t
);
242 iter
= set
->nextchild
;
244 if (bytes_identical(iter
->name
, name
))
246 if (iter
->nextsib
!= NULL
)
247 { iter
= iter
->nextsib
;
250 iter
= struct_alloc(ir_set_t
);
251 iter
->nextsib
= set
->nextchild
;
252 return set
->nextchild
= iter
;
255 /* Add a framebox to a set
256 Attempts to create a new framebox of the specified set, returning
257 the framebox if it already exists
260 struct ir_framebox_t
* ir_set_add_framebox
261 ( struct ir_set_t
* set
,
264 { struct ir_framebox_t
* iter
;
265 if (set
->frameboxes
== NULL
)
266 return set
->frameboxes
= struct_alloc(ir_framebox_t
);
267 iter
= set
->frameboxes
;
269 if (bytes_identical(iter
->header
.data_name
, name
))
271 if (iter
->header
.nextsib
!= NULL
)
272 { iter
= (struct ir_framebox_t
*) iter
->header
.nextsib
;
275 iter
= struct_alloc(ir_framebox_t
);
276 iter
->header
.nextsib
= (union ir_setdata_t
*) set
->frameboxes
;
277 return set
->frameboxes
= iter
;
280 /* Match two null-terminated bytestrings
281 Return 1 if the two bytestrings are identical, else 0
292 } while (ca
&& ca
== cb
);
296 /* Assign Setdata to Set
299 void ir_set_assign_data
300 ( struct ir_set_t
* set
,
301 union ir_setdata_t
* setdata
303 { struct ir_framebox_t
* framebox
;
304 struct ir_simplex_t
* simplex
;
305 switch (setdata
->header
.type
)
307 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
308 if (framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
309 wprintf("Duplicate framesheet [%i] %s\n",
310 setdata
->framesheet
.frameinfo
.facing
, setdata
->header
.data_name
);
311 framebox
->framesheets
[setdata
->framesheet
.frameinfo
.facing
] = setdata
->framesheet
;
314 framebox
= ir_set_add_framebox(set
, setdata
->header
.data_name
);
315 if (framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
].header
.data_name
!= NULL
)
316 wprintf("Duplicate mapsheet [%i] %s\n",
317 setdata
->mapsheet
.frameinfo
.facing
, setdata
->header
.data_name
);
318 framebox
->mapsheets
[setdata
->mapsheet
.frameinfo
.facing
] = setdata
->mapsheet
;
321 if (set
->audio
== NULL
)
322 { set
->audio
= (struct ir_simplex_t
*) setdata
;
325 simplex
= set
->audio
;
326 while (simplex
->header
.nextsib
!= NULL
)
327 if (bytes_identical(simplex
->header
.data_name
, setdata
->header
.data_name
))
328 { wprintf("Duplicate audio %s\n", setdata
->header
.data_name
);
329 *simplex
= setdata
->audio
;
330 //setdata is now a pointer to redundant, unused memory.
334 simplex
= (struct ir_simplex_t
*) simplex
->header
.nextsib
;
335 simplex
->header
.nextsib
= setdata
;
338 setdata
->link
.header
.nextsib
= (union ir_setdata_t
*) set
->links
;
339 set
->links
= (struct ir_link_t
*) setdata
;
342 fprintf(stderr
, "Unknown setdata type %x\n", setdata
->header
.type
);
347 void ir_set_assign_ref
348 ( struct ir_set_t
* set
,
352 wprintf("Ref override: 0x%lx -> 0x%lx for set %s\n",
353 (long unsigned) set
->ref
, (long unsigned) ref
, set
->name
);
355 //TODO: reflist_add(set);
358 void ir_data_assign_path
359 ( union ir_setdata_t
* setdata
,
362 { setdata
->header
.src_filename
= path
;
363 //TODO: internal strdup, not assign (= path;)
367 //TODO: Macro ir_framsheet and mapsheet?
368 union ir_setdata_t
* ir_framesheet
374 { struct ir_framedata_t
* framesheet
= struct_alloc(ir_framedata_t
);
375 framesheet
->header
.type
= FSDAT
;
376 framesheet
->header
.data_name
= name
;
377 framesheet
->frameinfo
.facing
= d
;
378 framesheet
->frameinfo
.w
= width
;
379 framesheet
->frameinfo
.h
= height
;
380 return (union ir_setdata_t
*) framesheet
;
383 union ir_setdata_t
* ir_mapsheet
389 { struct ir_framedata_t
* mapsheet
= struct_alloc(ir_framedata_t
);
390 mapsheet
->header
.type
= MSDAT
;
391 mapsheet
->header
.data_name
= name
;
392 mapsheet
->frameinfo
.facing
= d
;
393 mapsheet
->frameinfo
.w
= width
;
394 mapsheet
->frameinfo
.h
= height
;
395 return (union ir_setdata_t
*) mapsheet
;
398 union ir_setdata_t
* ir_audio
400 { struct ir_simplex_t
* audio
= struct_alloc(ir_simplex_t
);
401 audio
->header
.type
= ADAT
;
402 audio
->header
.data_name
= name
;
403 return (union ir_setdata_t
*) audio
;
407 void* stack_alloc(size_t bytes
)
409 { wprint("Attempting to allocate 0 bytes in stack_alloc");
410 return pagenode_head
->head
;
412 if (PN_HEADSPACE() < bytes
)
413 { pagenode_head
->next
= (struct pagenode_t
*) calloc(PN_ALLOCSIZE
,1);
414 pagenode_head
= pagenode_head
->next
;
415 pagenode_head
->head
= pagenode_head
->root
;
417 pagenode_head
->head
+= bytes
;
418 return (void*) pagenode_head
->head
- bytes
;