1 /*-
2 * Copyright (c) 2001 Lev Walkin <vlm@lionet.info>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: memmem.c,v 1.3 2005/03/03 20:35:26 vlm Exp $
27 */
28
29 #include "intern.h"
30 #include "libmimedir.h"
31
32 struct mdir_memchunk {
33 void *p;
34 struct mdir_memchunk *next;
35 };
36
37
38 int
_mdir_mem_replacechunk(struct mdir_memchunk * mdm,void * op,void * p)39 _mdir_mem_replacechunk(struct mdir_memchunk *mdm, void *op, void *p) {
40 if(!mdm)
41 return -1;
42
43 if(mdm->p == op) {
44 mdm->p = p;
45 return 0;
46 }
47
48 return _mdir_mem_replacechunk(mdm->next, op, p);
49 }
50
51 void *
_mdir_mem_realloc(void ** arg,void * op,size_t size)52 _mdir_mem_realloc(void **arg, void *op, size_t size) {
53 void *p;
54
55 p = realloc(op, size);
56
57 if(op != p)
58 _mdir_mem_replacechunk((struct mdir_memchunk *)*arg, op, p);
59
60 return p;
61 }
62
63 int
_mdir_mem_forgetchunk2(struct mdir_memchunk * mdm,void * p)64 _mdir_mem_forgetchunk2(struct mdir_memchunk *mdm, void *p) {
65 if(!mdm)
66 return -1;
67
68 if(mdm->p == p) {
69 mdm->p = NULL;
70 return 0;
71 }
72
73 return _mdir_mem_forgetchunk2(mdm->next, p);
74 }
75
76 void
_mdir_mem_forgetchunk(void ** arg,void * p)77 _mdir_mem_forgetchunk(void **arg, void *p) {
78 if(_mdir_mem_forgetchunk2((struct mdir_memchunk *)*arg, p)) {
79 fprintf(stderr, "forgetchunk() on not allocated data: %p\n", p);
80 abort();
81 }
82 }
83
84 void
_mdir_mem_free(void ** arg,void * p)85 _mdir_mem_free(void **arg, void *p) {
86 if(_mdir_mem_forgetchunk2((struct mdir_memchunk *)*arg, p)) {
87 fprintf(stderr, "free() on not allocated data: %p\n", p);
88 abort();
89 } else {
90 free(p);
91 }
92 }
93
94
95 int
_mdir_mem_addchunk(void ** arg,void * p)96 _mdir_mem_addchunk(void **arg, void *p) {
97 struct mdir_memchunk *mch;
98
99 mch = (struct mdir_memchunk *)malloc(sizeof(struct mdir_memchunk));
100 if(!mch)
101 return -1;
102
103 /* Add to the head */
104 mch->next = *arg;
105 mch->p = p;
106 *arg = mch;
107
108 return 0;
109 };
110
111 void
_mdir_mem_forget2(struct mdir_memchunk * mdm,int freeit)112 _mdir_mem_forget2(struct mdir_memchunk *mdm, int freeit) {
113 if(!mdm)
114 return;
115
116 if(freeit && mdm->p) {
117 free(mdm->p);
118 }
119
120 /* One test or every chunk test? To be, or not to be? */
121 _mdir_mem_forget2(mdm->next, freeit);
122
123 free(mdm);
124 };
125
126 void
_mdir_mem_forget(void ** arg,int freeit)127 _mdir_mem_forget(void **arg, int freeit) {
128 _mdir_mem_forget2((struct mdir_memchunk *)*arg, freeit);
129 *(void **)arg = NULL;
130 };
131
132 void *
_mdir_mem_malloc(void ** arg,size_t size)133 _mdir_mem_malloc(void **arg, size_t size) {
134 void *p;
135
136 p = malloc(size);
137 if(!p)
138 return NULL;
139
140 if(_mdir_mem_addchunk(arg, p)) {
141 free(p);
142 return NULL;
143 };
144
145 return p;
146 };
147
148 char *
_mdir_mem_strdup(void ** arg,char * str)149 _mdir_mem_strdup(void **arg, char *str) {
150 char *p;
151
152 p = strdup(str);
153 if(!p) return NULL;
154
155 if(_mdir_mem_addchunk(arg, p)) {
156 free(p);
157 return NULL;
158 };
159
160 return p;
161 };
162
163 char *
_mdir_mem_stradd(void ** arg,char * src,char * str)164 _mdir_mem_stradd(void **arg, char *src, char *str) {
165 size_t len;
166 char *p;
167
168 len = strlen(src);
169
170 p = (char *)_mdir_mem_realloc(arg, src, len + strlen(str) + 1);
171 if(!p) {
172 _mdir_mem_free(arg, src);
173 return NULL;
174 }
175
176 strcpy(p + len, str);
177
178 return p;
179 }
180
181 size_t
_mdir_count_values(char ** list)182 _mdir_count_values(char **list) {
183 size_t z;
184
185 if(!list)
186 return 0;
187
188 for(z = 0; *list; list++, z++);
189
190 return z;
191 }
192
193 char **
_mdir_mem_list_extend(void ** arg,char *** list)194 _mdir_mem_list_extend(void **arg, char ***list) {
195 char **p;
196 size_t cv;
197
198 if(!list) {
199 p = (char **)_mdir_mem_malloc(arg, sizeof(char *) << 1);
200 p[0] = NULL;
201 p[1] = NULL;
202 return p;
203 }
204
205 cv = _mdir_count_values(*list);
206 p = (char **)_mdir_mem_realloc(arg, *list, (cv + 2) * sizeof(char *));
207 if(!p)
208 return NULL;
209
210 p[cv + 1] = NULL;
211 *list = p;
212
213 return p + cv;
214 }
215
216 void
_mdir_list_free(char ** list)217 _mdir_list_free(char **list) {
218 char **vp;
219 for(vp = list; *vp; vp++)
220 free(*vp);
221 free(list);
222 }
223
224
225