comparison src/libmlk-core/core/alloc.c @ 320:8f9937403749

misc: improve loading of data
author David Demelier <markand@malikania.fr>
date Fri, 01 Oct 2021 20:30:00 +0200
parents libmlk-core/core/alloc.c@d01e83210ca2
children 460c78706989
comparison
equal deleted inserted replaced
319:b843eef4cc35 320:8f9937403749
1 /*
2 * alloc.h -- custom allocators
3 *
4 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <assert.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <SDL.h>
25
26 #include "alloc.h"
27 #include "error.h"
28 #include "panic.h"
29
30 static void *
31 panic_alloc(size_t size)
32 {
33 void *mem;
34
35 if (!(mem = malloc(size)))
36 panicf("%s", strerror(errno));
37
38 return mem;
39 }
40
41 static void *
42 panic_realloc(void *ptr, size_t size)
43 {
44 void *mem;
45
46 if (!(mem = realloc(ptr, size)) && size != 0)
47 panicf("%s", strerror(errno));
48
49 return mem;
50 }
51
52 static const struct alloc_funcs default_alloc_funcs = {
53 .alloc = panic_alloc,
54 .realloc = panic_realloc,
55 .free = free
56 };
57
58 static const struct alloc_funcs *funcs = &default_alloc_funcs;
59
60 void
61 alloc_set(const struct alloc_funcs *newfuncs)
62 {
63 assert(funcs);
64 assert(funcs->alloc);
65 assert(funcs->realloc);
66 assert(funcs->free);
67
68 funcs = newfuncs;
69
70 /* Change SDL allocators as well. */
71 SDL_SetMemoryFunctions(alloc_new, alloc_array0, alloc_renew, free);
72 }
73
74 void *
75 alloc_new(size_t size)
76 {
77 assert(size != 0);
78
79 return funcs->alloc(size);
80 }
81
82 void *
83 alloc_new0(size_t size)
84 {
85 assert(size != 0);
86
87 void *ptr;
88
89 if ((ptr = funcs->alloc(size)))
90 memset(ptr, 0, size);
91
92 return ptr;
93 }
94
95 void *
96 alloc_array(size_t len, size_t elemsize)
97 {
98 assert(len != 0);
99 assert(elemsize != 0);
100
101 size_t size = len * elemsize;
102
103 if (size / len != elemsize)
104 return errorf("%s", strerror(ENOMEM)), NULL;
105
106 return funcs->alloc(size);
107 }
108
109 void *
110 alloc_array0(size_t len, size_t elemsize)
111 {
112 assert(len != 0);
113 assert(elemsize != 0);
114
115 void *mem;
116 size_t size = len * elemsize;
117
118 if (size / len != elemsize)
119 return errorf("%s", strerror(ENOMEM)), NULL;
120
121 if ((mem = funcs->alloc(size)))
122 memset(mem, 0, size);
123
124 return mem;
125 }
126
127 void *
128 alloc_renew(void *ptr, size_t size)
129 {
130 return funcs->realloc(ptr, size);
131 }
132
133 void *
134 alloc_rearray(void *ptr, size_t len, size_t elemsize)
135 {
136 size_t size = len * elemsize;
137
138 if (size / len != elemsize)
139 return errorf("%s", strerror(ENOMEM)), NULL;
140
141 return funcs->realloc(ptr, size);
142 }
143
144 void *
145 alloc_rearray0(void *ptr, size_t oldlen, size_t newlen, size_t elemsize)
146 {
147 size_t size = newlen * elemsize;
148
149 if (size / newlen != elemsize)
150 return errorf("%s", strerror(ENOMEM)), NULL;
151 if (!(ptr = funcs->realloc(ptr, size)))
152 return NULL;
153
154 if (newlen > oldlen)
155 memset((unsigned char *)ptr + (oldlen * elemsize), 0, (newlen - oldlen) * elemsize);
156
157 return ptr;
158 }
159
160 void *
161 alloc_dup(const void *ptr, size_t size)
162 {
163 assert(ptr);
164 assert(size != 0);
165
166 void *mem;
167
168 if ((mem = funcs->alloc(size)))
169 memcpy(mem, ptr, size);
170
171 return mem;
172 }
173
174 char *
175 alloc_sdup(const char *src)
176 {
177 assert(src);
178
179 char *ret;
180 size_t length = strlen(src) + 1;
181
182 if ((ret = funcs->alloc(length)))
183 memcpy(ret, src, length + 1);
184
185 return ret;
186 }
187
188 int
189 alloc_pool_init(struct alloc_pool *pool, size_t elemsize, void (*finalizer)(void *))
190 {
191 assert(pool);
192 assert(elemsize != 0);
193
194 if (!(pool->data = alloc_array(ALLOC_POOL_INIT_DEFAULT, elemsize)))
195 return -1;
196
197 pool->elemsize = elemsize;
198 pool->size = 0;
199 pool->capacity = ALLOC_POOL_INIT_DEFAULT;
200 pool->finalizer = finalizer;
201
202 return 0;
203 }
204
205 void *
206 alloc_pool_new(struct alloc_pool *pool)
207 {
208 assert(pool);
209
210 if (pool->size >= pool->capacity) {
211 void *newptr = alloc_rearray(pool->data, pool->capacity * 2, pool->elemsize);
212
213 if (!newptr)
214 return NULL;
215
216 pool->data = newptr;
217 pool->capacity *= 2;
218 }
219
220 return ((unsigned char *)pool->data) + pool->size++ * pool->elemsize;
221 }
222
223 void *
224 alloc_pool_get(const struct alloc_pool *pool, size_t index)
225 {
226 assert(pool);
227 assert(index < pool->size);
228
229 return ((unsigned char *)pool->data) + index * pool->elemsize;
230 }
231
232 void
233 alloc_pool_finish(struct alloc_pool *pool)
234 {
235 if (pool->finalizer) {
236 unsigned char *tab = pool->data;
237
238 for (size_t i = 0; i < pool->size; ++i)
239 pool->finalizer(tab + i * pool->elemsize);
240 }
241
242 free(pool->data);
243 memset(pool, 0, sizeof (*pool));
244 }