Use offsetof macro where possible to defined header size;
[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 mcalloc(MemoryContext *cntx, size_t size) {
166         MemoryChunk     *chunk = cntx->chunk;
167         MCAllocatedSpace *alloc;
168
169         size = PTRALIGN(size) + MCASHDRSZ;
170         if ( cntx->flags & MC_DEBUG )
171                 size += sizeof(u_int32_t);
172
173         if ( chunk->freesize < size ) {
174                 MemoryChunk     *newchunk;
175
176                 if ( size >= CNTXCHUNK ) {
177                         newchunk = (MemoryChunk*)tmalloc(MEMCHNKHDRSZ + size);
178                         newchunk->size = newchunk->freesize = size;
179                         newchunk->next = chunk->next;
180                         chunk->next = newchunk;
181                 } else {
182                         newchunk = (MemoryChunk*)tmalloc(MEMCHNKHDRSZ + CNTXCHUNK);
183                         newchunk->size = newchunk->freesize = CNTXCHUNK;
184                         newchunk->next = chunk;
185                         cntx->chunk = newchunk; 
186                 }
187
188                 chunk = newchunk;
189         }
190
191         alloc = (MCAllocatedSpace*)( chunk->data + chunk->size - chunk->freesize );
192         alloc->size = size; 
193         alloc->cntx = cntx;
194         chunk->freesize -= size;
195  
196         if ( cntx->flags & MC_DEBUG ) {
197                 *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) = MCMAGICKNUMBER;
198                 memset( alloc->data, 0xc3, size - MCASHDRSZ - sizeof(u_int32_t) ); 
199         }
200
201         return (void*)(alloc->data);
202 }
203
204 void *
205 mc0alloc(MemoryContext *cntx, size_t size) {
206         void *res = mcalloc(cntx, size);
207         memset( res, 0, size );
208         return res;
209 }
210
211 void *
212 mcrealloc(void * ptr, size_t size) {
213         MCAllocatedSpace        *alloc = (MCAllocatedSpace*)( (char*)ptr - MCASHDRSZ );
214         size_t realsize;
215
216         if ( ptr==NULL )
217                 tlog(TL_CRIT|TL_EXIT, "mcrealloc: realloc null pointer");
218
219         if ( alloc->cntx->flags & MC_DEBUG ) {
220                 tassert(  *(u_int32_t*)( (char*)alloc + alloc->size - sizeof(u_int32_t) ) == MCMAGICKNUMBER );
221                 realsize = alloc->size - MCASHDRSZ - sizeof(u_int32_t); 
222         } else
223                 realsize = alloc->size - MCASHDRSZ;
224
225         if ( size > realsize ) {
226                 MemoryChunk *chunk = alloc->cntx->chunk;
227                 if ( (char*)alloc == chunk->data + chunk->size - chunk->freesize - alloc->size &&
228                                 PTRALIGN(size)-realsize <= alloc->cntx->chunk->freesize ) {
229                         /* just enlarge */
230                         alloc->cntx->chunk->freesize -= PTRALIGN(size)-realsize;
231                         alloc->size+=PTRALIGN(size)-realsize;
232                         if ( alloc->cntx->flags & MC_DEBUG ) {
233                                 memset( (char*)(alloc->data) + realsize,  0xc3, PTRALIGN(size)-realsize );
234                                 *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) = MCMAGICKNUMBER;
235                         }
236                 } else {  
237                         void *newptr = mcalloc(alloc->cntx, size);
238                         memcpy( newptr, ptr, realsize );
239                         ptr = newptr;
240                         if ( alloc->cntx->flags & MC_DEBUG ) 
241                                 memset( (char*)ptr + realsize, 0xc3, PTRALIGN(size)-realsize );
242                 }
243         }
244  
245         return ptr;
246 }
247
248
249 void    
250 mcfree(void * ptr) {
251         MCAllocatedSpace        *alloc = (MCAllocatedSpace*)( (char*)ptr - MCASHDRSZ );
252         MemoryChunk *chunk;
253
254         if ( ptr==NULL )
255                 tlog(TL_CRIT|TL_EXIT, "mcfree: free null pointer");
256
257         if ( alloc->cntx->flags & MC_DEBUG ) 
258                 tassert(  *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) == MCMAGICKNUMBER );
259
260         chunk = alloc->cntx->chunk;
261         if ( (char*)alloc == chunk->data + chunk->size - chunk->freesize - alloc->size ) /* last allocated value */
262                 alloc->cntx->chunk->freesize+=alloc->size;
263
264         alloc->cntx=NULL;
265 }
266
267 char * 
268 mcstrdup(MemoryContext *cntx, char * src) {
269         return mcnstrdup(cntx, src, strlen(src));
270 }
271
272 char *
273 mcnstrdup(MemoryContext *cntx, char *src, int len) {
274         char *dest=(char*)mcalloc(cntx, len+1);
275         memcpy(dest, src, len);
276         dest[len]='\0';
277         return dest;
278 }
279