Sync mem.[ch] with pwmd. Prepends elements rather than appending among
[libpwmd.git] / mem.c
blob667a094974970067a7844a5ab5de182fa1196257
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2008 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <assert.h>
24 #include <err.h>
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
30 #include "gettext.h"
31 #define N_(msgid) gettext(msgid)
33 #include "mem.h"
35 static struct memlist_s *memlist;
36 #ifdef DEBUG
37 static size_t allocations, deallocations;
38 #endif
40 static struct memlist_s *memlist_remove(struct memlist_s *list, struct memlist_s *r)
42 struct memlist_s *m, *last = NULL, *p;
44 for (m = list; m; m = m->next) {
45 if (m->ptr == r->ptr) {
46 memset(m->ptr, 0, m->size);
47 free(m->ptr);
49 p = m->next;
50 free(m);
51 #ifdef DEBUG
52 deallocations++;
53 #endif
55 if (last) {
56 if (p)
57 last->next = p;
58 else
59 last->next = NULL;
61 else if (p)
62 list = p;
63 else
64 list = NULL;
66 break;
69 last = m;
72 return list;
75 static struct memlist_s *memlist_prepend(struct memlist_s *list, struct memlist_s *p)
77 #ifdef DEBUG
78 allocations++;
79 #endif
80 p->next = list;
81 return p;
84 void xfree(void *ptr)
86 struct memlist_s *m;
88 if (!ptr)
89 return;
91 for (m = memlist; m; m = m->next) {
92 if (m->ptr == ptr) {
93 #ifdef DEBUG
94 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, ptr, m->size);
95 #endif
96 memlist = memlist_remove(memlist, m);
97 return;
101 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
102 assert(0);
105 void *xmalloc(size_t size)
107 void *p;
108 struct memlist_s *m;
110 if (size <= 0)
111 return NULL;
113 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
114 return NULL;
116 if ((p = malloc(size)) == NULL) {
117 free(m);
118 return NULL;
121 m->ptr = p;
122 m->size = size;
123 memlist = memlist_prepend(memlist, m);
124 #ifdef DEBUG
125 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
126 #endif
127 return m->ptr;
130 void *xcalloc(size_t nmemb, size_t size)
132 void *p;
133 struct memlist_s *m;
135 if (size <= 0)
136 return NULL;
138 if ((m = (struct memlist_s *)malloc(sizeof(struct memlist_s))) == NULL)
139 return NULL;
141 if ((p = calloc(nmemb, size)) == NULL) {
142 free(m);
143 return NULL;
146 m->ptr = p;
147 m->size = nmemb * size;
148 memlist = memlist_prepend(memlist, m);
149 #ifdef DEBUG
150 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, nmemb * size);
151 #endif
152 return m->ptr;
155 void *xrealloc(void *ptr, size_t size)
157 void *p;
158 struct memlist_s *m;
160 if (!ptr)
161 return xmalloc(size);
163 if (size <= 0)
164 return ptr;
166 for (m = memlist; m; m = m->next) {
167 if (m->ptr == ptr) {
168 if ((p = malloc(size)) == NULL)
169 return NULL;
171 memcpy(p, m->ptr, size < m->size ? size : m->size);
172 memset(m->ptr, 0, m->size);
173 free(m->ptr);
174 m->ptr = p;
175 m->size = size;
176 #ifdef DEBUG
177 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, p, size);
178 #endif
179 return m->ptr;
183 warnx(N_("%s: %p not found"), __FUNCTION__, ptr);
184 assert(0);
185 return NULL;
188 char *xstrdup(const char *str)
190 char *t, *tp;
191 size_t len;
192 const char *p;
194 if (!str)
195 return NULL;
197 len = strlen(str) + 1;
199 if ((t = (char *)xmalloc(len * sizeof(char))) == NULL)
200 return NULL;
202 for (p = str, tp = t; *p; p++)
203 *tp++ = *p;
205 *tp = 0;
206 #ifdef DEBUG
207 fprintf(stderr, "%s: %p\n", __FUNCTION__, t);
208 #endif
209 return t;
212 void xpanic(void)
214 struct memlist_s *m;
216 for (m = memlist; m; m = memlist)
217 xfree(m->ptr);
220 #ifdef DEBUG
221 void xdump(void)
223 struct memlist_s *m;
224 size_t total = 0;
226 for (m = memlist; m; m = m->next) {
227 fprintf(stderr, "%s: %p %i\n", __FUNCTION__, m->ptr, m->size);
228 total += m->size;
231 fprintf(stderr, "Total unfreed: %i bytes, allocations: %i, deallocations: %i\n", total,
232 allocations, deallocations);
234 #endif