Fix memory leak in GListTruncate
[tedtools.git] / tmalloc.c
1 /*
2  * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
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  * 3. Neither the name of the author nor the names of any co-contributors
14  *        may be used to endorse or promote products derived from this software
15  *        without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33
34 #include "tlog.h"
35 #include "tmalloc.h"
36
37 void *
38 tmalloc(size_t size) {
39         void *ptr = malloc(size);
40         if (!ptr)
41                 tlog(TL_CRIT|TL_EXIT, "Can't allocate %d bytes", size);
42         return ptr;
43 }
44
45 void *
46 t0malloc(size_t size) {
47         void *ptr = tmalloc(size);
48         memset(ptr,0,size);
49         return ptr;
50 }
51
52 void *
53 trealloc(void * ptr, size_t size) {
54         if (ptr) {
55                 ptr = realloc(ptr,size);
56                 if (!ptr)
57                         tlog(TL_CRIT|TL_EXIT, "Can't reallocate to %d bytes", size);
58         } else
59                 ptr = tmalloc(size);    
60         return ptr;
61 }
62
63 void
64 tfree(void * ptr) {
65         free(ptr);
66 }
67
68 char * 
69 tstrdup(char * src) {
70         char * dest = strdup(src);
71         if (!dest) 
72                 tlog(TL_CRIT|TL_EXIT, "Can't strdup %d bytes", strlen(src)+1);
73         return dest;
74 }
75
76 char *
77 tnstrdup(char *src, int len) {
78         char *dest=(char*)tmalloc(len+1);
79         memcpy(dest, src, len);
80         dest[len]='\0';
81         return dest;
82 }
83
84 char *
85 strlower(char * src) {
86         char *ptr = src;
87         if (!src) return src;
88         while(*ptr) {
89                 *ptr = tolower(*(unsigned char *) ptr);
90                 ptr++; 
91         }
92         return src;
93 }
94
95 char *
96 strupper(char * src) {
97         char *ptr = src;
98         if (!src) return src;
99         while(*ptr) {
100                 *ptr = toupper(*(unsigned char *) ptr);
101                 ptr++; 
102         }
103         return src;
104 }
105
106 int
107 clrspace(char *buf) {
108         char *ptr=buf, *ptrc=buf;
109         while(*ptr) {
110                 if (!isspace(*ptr)) {
111                         *ptrc=*ptr;
112                         ptrc++;
113                 }
114                 ptr++;
115         }
116         *ptrc='\0';
117         return ptrc - buf;
118 }
119
120
121 MemoryContext *
122 allocMemoryContext(MemoryContext* parent, int flags) {
123         MemoryContext *res;
124
125         res = (MemoryContext*)tmalloc( sizeof(MemoryContext) );
126         res->flags = flags;
127         res->parent = parent;
128         if ( parent ) {
129                 res->child = parent->child;
130                 parent->child = res;
131         } else
132                 res->child = NULL;
133
134         res->chunk = (MemoryChunk*)tmalloc( MEMCHNKHDRSZ + CNTXCHUNK );
135         res->chunk->size = res->chunk->freesize = CNTXCHUNK;
136         res->chunk->next = NULL;
137
138         return res;
139 }
140
141 void
142 freeMemoryContext(MemoryContext *cntx) {
143         MemoryContext   *ptr=cntx;
144         MemoryChunk     *chunk, *chunkptr;
145
146         if ( cntx->parent )
147                 cntx->parent->child=NULL;
148
149         while( ptr ) {
150                 cntx=ptr->child;
151
152                 chunkptr=ptr->chunk;
153                 while( chunkptr ) {
154                         chunk=chunkptr->next;
155                         tfree(chunkptr);
156                         chunkptr=chunk;
157                 }
158                 
159                 tfree(ptr);
160                 ptr=cntx;
161         }
162 }
163
164 void
165 resetMemoryContext(MemoryContext *cntx) {
166         MemoryChunk *chunk, *chunkptr;
167
168         while( cntx ) {
169                 chunkptr = cntx->chunk;
170                 chunkptr->freesize = chunkptr->size;
171                 chunkptr = chunkptr->next;
172                 cntx->chunk->next = NULL;
173
174                 while( chunkptr ) {
175                         chunk=chunkptr->next;
176                         tfree(chunkptr);
177                         chunkptr=chunk;
178                 }
179                 cntx=cntx->child;
180         }
181 }
182
183 void*   
184 mcalloc(MemoryContext *cntx, size_t size) {
185         MemoryChunk     *chunk = cntx->chunk;
186         MCAllocatedSpace *alloc;
187
188         size = PTRALIGN(size) + MCASHDRSZ;
189         if ( cntx->flags & MC_DEBUG )
190                 size += sizeof(u_int32_t);
191
192         if ( chunk->freesize < size ) {
193                 MemoryChunk     *newchunk;
194
195                 if ( size >= CNTXCHUNK ) {
196                         newchunk = (MemoryChunk*)tmalloc(MEMCHNKHDRSZ + size);
197                         newchunk->size = newchunk->freesize = size;
198                         newchunk->next = chunk->next;
199                         chunk->next = newchunk;
200                 } else {
201                         newchunk = (MemoryChunk*)tmalloc(MEMCHNKHDRSZ + CNTXCHUNK);
202                         newchunk->size = newchunk->freesize = CNTXCHUNK;
203                         newchunk->next = chunk;
204                         cntx->chunk = newchunk; 
205                 }
206
207                 chunk = newchunk;
208         }
209
210         alloc = (MCAllocatedSpace*)( chunk->data + chunk->size - chunk->freesize );
211         alloc->size = size; 
212         alloc->cntx = cntx;
213         chunk->freesize -= size;
214  
215         if ( cntx->flags & MC_DEBUG ) {
216                 *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) = MCMAGICKNUMBER;
217                 memset( alloc->data, 0xc3, size - MCASHDRSZ - sizeof(u_int32_t) ); 
218         }
219
220         return (void*)(alloc->data);
221 }
222
223 void *
224 mc0alloc(MemoryContext *cntx, size_t size) {
225         void *res = mcalloc(cntx, size);
226         memset( res, 0, size );
227         return res;
228 }
229
230 void *
231 mcrealloc(void * ptr, size_t size) {
232         MCAllocatedSpace        *alloc = (MCAllocatedSpace*)( (char*)ptr - MCASHDRSZ );
233         size_t realsize;
234
235         if ( ptr==NULL )
236                 tlog(TL_CRIT|TL_EXIT, "mcrealloc: realloc null pointer");
237
238         if ( alloc->cntx->flags & MC_DEBUG ) {
239                 tassert(  *(u_int32_t*)( (char*)alloc + alloc->size - sizeof(u_int32_t) ) == MCMAGICKNUMBER );
240                 realsize = alloc->size - MCASHDRSZ - sizeof(u_int32_t); 
241         } else
242                 realsize = alloc->size - MCASHDRSZ;
243
244         if ( size > realsize ) {
245                 MemoryChunk *chunk = alloc->cntx->chunk;
246                 if ( (char*)alloc == chunk->data + chunk->size - chunk->freesize - alloc->size &&
247                                 PTRALIGN(size)-realsize <= alloc->cntx->chunk->freesize ) {
248                         /* just enlarge */
249                         alloc->cntx->chunk->freesize -= PTRALIGN(size)-realsize;
250                         alloc->size+=PTRALIGN(size)-realsize;
251                         if ( alloc->cntx->flags & MC_DEBUG ) {
252                                 memset( (char*)(alloc->data) + realsize,  0xc3, PTRALIGN(size)-realsize );
253                                 *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) = MCMAGICKNUMBER;
254                         }
255                 } else {  
256                         void *newptr = mcalloc(alloc->cntx, size);
257                         memcpy( newptr, ptr, realsize );
258                         ptr = newptr;
259                         if ( alloc->cntx->flags & MC_DEBUG ) 
260                                 memset( (char*)ptr + realsize, 0xc3, PTRALIGN(size)-realsize );
261                 }
262         }
263  
264         return ptr;
265 }
266
267
268 void    
269 mcfree(void * ptr) {
270         MCAllocatedSpace        *alloc = (MCAllocatedSpace*)( (char*)ptr - MCASHDRSZ );
271         MemoryChunk *chunk;
272
273         if ( ptr==NULL )
274                 tlog(TL_CRIT|TL_EXIT, "mcfree: free null pointer");
275
276         if ( alloc->cntx->flags & MC_DEBUG ) 
277                 tassert(  *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) == MCMAGICKNUMBER );
278
279         chunk = alloc->cntx->chunk;
280         if ( (char*)alloc == chunk->data + chunk->size - chunk->freesize - alloc->size ) /* last allocated value */
281                 alloc->cntx->chunk->freesize+=alloc->size;
282
283         alloc->cntx=NULL;
284 }
285
286 char * 
287 mcstrdup(MemoryContext *cntx, char * src) {
288         return mcnstrdup(cntx, src, strlen(src));
289 }
290
291 char *
292 mcnstrdup(MemoryContext *cntx, char *src, int len) {
293         char *dest=(char*)mcalloc(cntx, len+1);
294         memcpy(dest, src, len);
295         dest[len]='\0';
296         return dest;
297 }
298