1 /* sswf_memory.c -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2009 */
2
3 /*
4
5 Copyright (c) 2002-2009 Made to Order Software Corp.
6
7 Permission is hereby granted, free of charge, to any
8 person obtaining a copy of this software and
9 associated documentation files (the "Software"), to
10 deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify,
12 merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the
15 following conditions:
16
17 The above copyright notice and this permission notice
18 shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
22 ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
24 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
25 EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 SOFTWARE.
31
32 */
33
34
35 #include "sswf.h"
36
37 #if DEBUG
38 struct mem_info_t {
39 unsigned long magic; /* the 'SSWF' identifier */
40 struct mem_info_t * next; /* link all the memory blocks */
41 struct mem_info_t * previous;
42 const char * name; /* some info about this memory buffer */
43 unsigned long serial; /* a counter */
44 size_t size; /* user allocation size */
45 };
46 #define SSWF_MEM_INFO_SIZEOF SSWF_MEM_ALIGN(sizeof(struct mem_info_t))
47 #define SSWF_MEM_INFO_MAGIC ((unsigned long) 0x53535746)
48
49 #define SSWF_MEM_SAFE (sizeof(double) * 32)
50 #define SSWF_MEM_TEST 0xBADC0FFE
51 #define SSWF_MEM_CLEAR 0xCB
52
53 static struct mem_info_t * mem_head;
54 static unsigned long mem_serial;
55
56
57 #else
58 #define SSWF_MEM_INFO_SIZEOF 0
59 #define SSWF_MEM_SAFE 0
60 #endif
61
62
63
64
65 #if DEBUG
sswf_alloc(size_t size,const char * name)66 void *sswf_alloc(size_t size, const char *name)
67 #else
68 void *sswf_alloc(size_t size)
69 #endif
70 {
71 #if DEBUG
72 long *l, *m;
73 int idx;
74 #endif
75 void *p;
76
77 p = malloc(((size + sizeof(long) - 1) & - (long) sizeof(long)) + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE * 2);
78 if(p == NULL) {
79 fprintf(stderr, "FATAL ERROR: out of memory allocating %d bytes.\n", (int) size);
80 exit(-1);
81 /*NOTREACHED*/
82 }
83
84 #if DEBUG
85 ((struct mem_info_t *) p)->magic = SSWF_MEM_INFO_MAGIC;
86 ((struct mem_info_t *) p)->next = mem_head;
87 if(mem_head != NULL) {
88 mem_head->previous = (struct mem_info_t *) p;
89 }
90 ((struct mem_info_t *) p)->previous = NULL;
91 mem_head = (struct mem_info_t *) p;
92 ((struct mem_info_t *) p)->name = name;
93 mem_serial++;
94 ((struct mem_info_t *) p)->serial = mem_serial;
95 ((struct mem_info_t *) p)->size = size;
96 l = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF);
97 p = (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE;
98 m = (long *) ((char *) p + ((size + sizeof(long) - 1) & - (long) sizeof(long)));
99 idx = SSWF_MEM_SAFE / sizeof(long);
100 do {
101 *l++ = *m++ = SSWF_MEM_TEST;
102 idx--;
103 } while(idx > 0);
104 #endif
105
106 return p;
107 }
108
109
110 #if DEBUG
sswf_test_safe(void * p,const char * what)111 static void sswf_test_safe(void *p, const char *what)
112 {
113 long *l, *m;
114 int idx, head, tail;
115
116 assert(((long) p & (SSWF_MEM_ALIGN_SIZE - 1)) == 0, "%s an unaligned memory buffer at %p", what, (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE);
117 assert(((struct mem_info_t *) p)->magic == SSWF_MEM_INFO_MAGIC, "%s a memory buffer without a magic marker at %p", what, (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE);
118 l = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF);
119 m = (long *) ((char *) l + SSWF_MEM_SAFE + ((((struct mem_info_t *) p)->size + sizeof(long) - 1) & - (long) sizeof(long)));
120 head = 0;
121 tail = 0;
122 idx = SSWF_MEM_SAFE / sizeof(long);
123 do {
124 if(*l++ != SSWF_MEM_TEST) {
125 head = 1;
126 }
127 if(*m++ != SSWF_MEM_TEST) {
128 tail = 1;
129 }
130 idx--;
131 } while(idx > 0);
132 if(head) {
133 /* an error occured, print out the corresponding data */
134 l = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF);
135 idx = SSWF_MEM_SAFE / sizeof(long);
136 do {
137 idx--;
138 if((idx & 7) == 7) {
139 printf("%08X- ", (unsigned int) (SSWF_MEM_SAFE - idx * sizeof(long)));
140 }
141 printf(" %08lX", *l++);
142 if((idx & 7) == 0) {
143 printf("\n");
144 }
145 } while(idx > 0);
146 }
147 if(tail) {
148 m = (long *) ((char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE + ((((struct mem_info_t *) p)->size + sizeof(long) - 1) & - (long) sizeof(long)));
149 idx = SSWF_MEM_SAFE / sizeof(long);
150 do {
151 idx--;
152 if((idx & 7) == 7) {
153 printf("%08X- ", (unsigned int) (SSWF_MEM_SAFE - idx * sizeof(long) + 256));
154 }
155 printf(" %08lX", *m++);
156 if((idx & 7) == 0) {
157 printf("\n");
158 }
159 } while(idx > 0);
160 }
161 assert(!head && !tail, "head and/or tail data was overwritten");
162 }
163 #endif
164
165
166
167 #if DEBUG
sswf_realloc(void * p,size_t size,const char * name)168 void *sswf_realloc(void *p, size_t size, const char *name)
169 #else
170 void *sswf_realloc(void *p, size_t size)
171 #endif
172 {
173 #if DEBUG
174 long *m;
175 int idx;
176
177 if(p == NULL) {
178 return sswf_alloc(size, name);
179 }
180
181 p = (char *) p - SSWF_MEM_INFO_SIZEOF - SSWF_MEM_SAFE;
182 sswf_test_safe(p, "reallocating");
183 #else
184 if(p == NULL) {
185 return sswf_alloc(size);
186 }
187 #endif
188 p = realloc(p, size + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE * 2);
189 if(p == NULL) {
190 fprintf(stderr, "FATAL ERROR: out of memory re-allocating %d bytes.\n", (int) size);
191 exit(-1);
192 /*NOTREACHED*/
193 }
194
195 #if DEBUG
196 /*((struct mem_info_t *) p)->magic = SSWF_MEM_INFO_MAGIC; -- shouldn't have changed */
197 /* p has changed so the next/previous of the previous/next nodes need fixing */
198 if(((struct mem_info_t *) p)->next != NULL) {
199 ((struct mem_info_t *) p)->next->previous = (struct mem_info_t *) p;
200 }
201 if(((struct mem_info_t *) p)->previous != NULL) {
202 ((struct mem_info_t *) p)->previous->next = (struct mem_info_t *) p;
203 }
204 else {
205 mem_head = (struct mem_info_t *) p;
206 }
207 ((struct mem_info_t *) p)->name = name;
208 mem_serial++;
209 ((struct mem_info_t *) p)->serial = mem_serial;
210 ((struct mem_info_t *) p)->size = size;
211 p = (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE;
212 m = (long *) ((char *) p + ((size + sizeof(long) - 1) & - (long) sizeof(long)));
213 idx = SSWF_MEM_SAFE / sizeof(long);
214 do {
215 *m++ = SSWF_MEM_TEST;
216 idx--;
217 } while(idx > 0);
218 #endif
219
220 return p;
221 }
222
223
224
sswf_free(void * p)225 void sswf_free(void *p)
226 {
227 /* accept NULL pointers */
228 if(p == NULL) {
229 return;
230 }
231 #if DEBUG
232 p = (char *) p - SSWF_MEM_INFO_SIZEOF - SSWF_MEM_SAFE;
233 sswf_test_safe(p, "freeing");
234
235 if(((struct mem_info_t *) p)->next != NULL) {
236 ((struct mem_info_t *) p)->next->previous = ((struct mem_info_t *) p)->previous;
237 }
238 if(((struct mem_info_t *) p)->previous != NULL) {
239 ((struct mem_info_t *) p)->previous->next = ((struct mem_info_t *) p)->next;
240 }
241 else {
242 mem_head = ((struct mem_info_t *) p)->next;
243 }
244 /* clear this buffer so we can't free it again and again */
245 memset(p, SSWF_MEM_CLEAR, ((struct mem_info_t *) p)->size + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE * 2);
246 #endif
247 free(p);
248 }
249
250
sswf_clean(void * p)251 void sswf_clean(void *p)
252 {
253 /* p is really a pointer to a pointer in this case */
254 if(p == NULL) {
255 return;
256 }
257 if(* (void **) p == NULL) {
258 return;
259 }
260 sswf_free(* (void **) p);
261 * (void **) p = NULL;
262 }
263
264
265
sswf_strdup(const char * string)266 char *sswf_strdup(const char *string)
267 {
268 int l;
269 char *r;
270
271 if(string == NULL) {
272 l = 1;
273 }
274 else {
275 l = strlen(string) + 1;
276 }
277
278 r = sswf_malloc(l, "dynamic string (strdup)");
279
280 if(l > 1) {
281 /* l includes the nul terminator */
282 memcpy(r, string, l);
283 }
284 else {
285 *r = '\0';
286 }
287
288 return r;
289 }
290
291
sswf_strcat(const char * a,const char * b)292 char *sswf_strcat(const char *a, const char *b)
293 {
294 int la, lb;
295 char *r;
296
297 if(a == NULL) {
298 return sswf_strdup(b);
299 }
300 if(b == NULL) {
301 return sswf_strdup(a);
302 }
303
304 la = strlen(a);
305 lb = strlen(b);
306
307 r = sswf_malloc(la + lb + 1, "dynamic string (sswf_strcat)");
308
309 if(la > 0) {
310 memcpy(r, a, la);
311 }
312 if(lb > 0) {
313 memcpy(r + la, b, lb);
314 }
315 r[la + lb] = '\0';
316
317 return r;
318 }
319
320
321
sswf_strcat3(const char * a,const char * b,const char * c)322 char *sswf_strcat3(const char *a, const char *b, const char *c)
323 {
324 int la, lb, lc;
325 char *r;
326
327 if(a == NULL) {
328 a = "";
329 }
330 if(b == NULL) {
331 b = "";
332 }
333 if(c == NULL) {
334 c = "";
335 }
336
337 la = strlen(a);
338 lb = strlen(b);
339 lc = strlen(c);
340
341 r = sswf_malloc(la + lb + lc + 1, "dynamic string (sswf_strcat3)");
342
343 if(la > 0) {
344 memcpy(r, a, la);
345 }
346 if(lb > 0) {
347 memcpy(r + la, b, lb);
348 }
349 if(lc > 0) {
350 memcpy(r + la + lb, c, lc);
351 }
352 r[la + lb + lc] = '\0';
353
354 return r;
355 }
356
357
358
sswf_strchild(const char * a,const char * b)359 char *sswf_strchild(const char *a, const char *b)
360 {
361 int la, lb;
362 const char *e;
363 char *r;
364
365 if(a == NULL) {
366 return sswf_strdup(b);
367 }
368 if(b == NULL) {
369 return sswf_strdup(a);
370 }
371
372 e = a;
373 while(*e != '\0') {
374 e++;
375 }
376 if(e > a && (e[-1] == '/' || e[-1] == '\\' || e[-1] == ':')) {
377 return sswf_strcat(a, b);
378 }
379
380 la = strlen(a);
381 lb = strlen(b);
382
383 r = sswf_malloc(la + lb + 2, "dynamic string (strcat)");
384
385 if(la > 0) {
386 memcpy(r, a, la);
387 }
388 r[la] = '/'; /* TODO: we need to fix this with the system separator instead */
389 if(lb > 0) {
390 memcpy(r + la + 1, b, lb);
391 }
392 r[la + lb + 1] = '\0';
393
394 return r;
395 }
396
397
398
399 #if DEBUG
sswf_info(void)400 void sswf_info(void)
401 {
402 struct mem_info_t *p;
403 size_t count, total;
404
405 printf("\n*** Memory Info:\n");
406 total = 0;
407 count = 0;
408 p = mem_head;
409 if(p == NULL) {
410 printf("!!! No memory leaks. Very good. !!!\n");
411 return;
412 }
413 if(p->previous != NULL) {
414 printf("+++ INVALID +++ First block not a head list block!\n");
415 }
416 while(p != NULL) {
417 if(p->magic != SSWF_MEM_INFO_MAGIC) {
418 printf("+++ INVALID +++ ");
419 }
420 count++;
421 printf("0x%08lX: Block #%06ld (Serial #%06ld) - %7ld bytes - %s", (long) ((char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE), (long) count, (long) p->serial, (long) p->size, p->name);
422 if(p->name != NULL && strncmp(p->name, "dynamic string", 14) == 0) {
423 printf(" [%s]", (char *) p + SSWF_MEM_INFO_SIZEOF + SSWF_MEM_SAFE);
424 }
425 printf("\n");
426 total += p->size;
427 p = p->next;
428 }
429
430 printf("Total of %ld blocks for %ld bytes.\n", (long) count, (long) total);
431 }
432
sswf_info_serial(void)433 void sswf_info_serial(void)
434 {
435 printf("At this point, the memory serial counter is #%ld\n", mem_serial);
436 }
437 #endif
438
439
440