Mirai's Miscellaneous Misadventures

M33 / core / allocators.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
3
4#include <mimimi/allocators.h>
5#include <mimimi/compound-behaviors.h>
6
7struct mimimi_temporary_allocator
8{
9	struct mimimi_allocator *allocator;
10	int count;
11	void **allocated;
12};
13
14static void *mimimi_temporary_allocate(void *data, unsigned int size)
15{
16	struct mimimi_temporary_allocator *temporary_allocator = data;
17	struct mimimi_allocator *allocator = temporary_allocator->allocator;
18	
19	void *value = mimimi_allocate(allocator, size);
20	
21	temporary_allocator->allocated = mimimi_reallocate(allocator, temporary_allocator->allocated, (temporary_allocator->count + 1) * sizeof *temporary_allocator->allocated);
22	temporary_allocator->allocated[temporary_allocator->count] = value;
23	temporary_allocator->count++;
24	
25	return value;
26}
27
28static void *mimimi_temporary_reallocate(void *data, void *value, unsigned int size)
29{
30	struct mimimi_temporary_allocator *temporary_allocator = data;
31	struct mimimi_allocator *allocator = temporary_allocator->allocator;
32	
33	if (value == allocator->null)
34		return mimimi_temporary_allocate(data, size);
35	
36	int i = 0;
37	while (temporary_allocator->allocated[i] != value) i++;
38	
39	value = mimimi_reallocate(allocator, value, size);
40	temporary_allocator->allocated[i] = value;
41	
42	return value;
43}
44
45static void mimimi_temporary_deallocate(void *data, void *value)
46{
47	struct mimimi_temporary_allocator *temporary_allocator = data;
48	struct mimimi_allocator *allocator = temporary_allocator->allocator;
49	
50	int i = 0;
51	while (temporary_allocator->allocated[i] != value) i++;
52	
53	for (int j = i + 1 ; j < temporary_allocator->count ; j++)
54		temporary_allocator->allocated[j - 1] = temporary_allocator->allocated[j];
55	
56	temporary_allocator->count--;
57	if (temporary_allocator->count == 0)
58		mimimi_deallocate(allocator, temporary_allocator->allocated),
59		temporary_allocator->allocated = allocator->null;
60	else
61		temporary_allocator->allocated = mimimi_reallocate(allocator, temporary_allocator->allocated, temporary_allocator->count * sizeof *temporary_allocator->allocated);
62	
63	mimimi_deallocate(temporary_allocator->allocator, value);
64}
65
66struct mimimi_allocator *mimimi_temporary_allocator(struct mimimi_allocator *allocator)
67{
68	struct mimimi_temporary_allocator *temporary_allocator = mimimi_allocate(allocator, sizeof *temporary_allocator);
69	temporary_allocator->allocator = allocator;
70	temporary_allocator->count = 0;
71	temporary_allocator->allocated = allocator->null;
72	
73	struct mimimi_allocator *result = mimimi_allocate(allocator, sizeof *result);
74	result->allocate = &mimimi_temporary_allocate;
75	result->deallocate = &mimimi_temporary_deallocate;
76	result->reallocate = &mimimi_temporary_reallocate;
77	result->null = allocator->null;
78	result->data = temporary_allocator;
79	
80	return result;
81}
82
83void mimimi_finish_temporary_allocator(struct mimimi_allocator *result)
84{
85	struct mimimi_temporary_allocator *temporary_allocator = result->data;
86	struct mimimi_allocator *allocator = temporary_allocator->allocator;
87	
88	for (int i = 0 ; i < temporary_allocator->count ; i++)
89		mimimi_deallocate(allocator, temporary_allocator->allocated[i]);
90	if (temporary_allocator->count != 0)
91		mimimi_deallocate(allocator, temporary_allocator->allocated);
92	mimimi_deallocate(allocator, temporary_allocator);
93	mimimi_deallocate(allocator, result);
94}
95
96static void mimimi_compound_allocator_finish(void *data)
97{
98	mimimi_finish_temporary_allocator(data);
99}
100
101struct mimimi_allocator *mimimi_compound_allocator(struct mimimi_behavior *compound, struct mimimi_allocator *allocator)
102{
103	struct mimimi_allocator *temporary_allocator = mimimi_temporary_allocator(allocator);
104	mimimi_compound(compound, mimimi_finalizer(temporary_allocator, &mimimi_compound_allocator_finish, allocator));
105	return temporary_allocator;
106}