/* * Copyright (c) 2004 Teodor Sigaev * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include "tlog.h" #include "tmalloc.h" void * tmalloc(size_t size) { void *ptr = malloc(size); if (!ptr) tlog(TL_CRIT|TL_EXIT, "Can't allocate %d bytes", size); return ptr; } void * t0malloc(size_t size) { void *ptr = tmalloc(size); memset(ptr,0,size); return ptr; } void * trealloc(void * ptr, size_t size) { if (ptr) { ptr = realloc(ptr,size); if (!ptr) tlog(TL_CRIT|TL_EXIT, "Can't reallocate to %d bytes", size); } else ptr = tmalloc(size); return ptr; } void tfree(void * ptr) { free(ptr); } char * tstrdup(char * src) { char * dest = strdup(src); if (!dest) tlog(TL_CRIT|TL_EXIT, "Can't strdup %d bytes", strlen(src)+1); return dest; } char * tnstrdup(char *src, int len) { char *dest=(char*)tmalloc(len+1); memcpy(dest, src, len); dest[len]='\0'; return dest; } char * strlower(char * src) { char *ptr = src; if (!src) return src; while(*ptr) { *ptr = tolower(*(unsigned char *) ptr); ptr++; } return src; } char * strupper(char * src) { char *ptr = src; if (!src) return src; while(*ptr) { *ptr = toupper(*(unsigned char *) ptr); ptr++; } return src; } int clrspace(char *buf) { char *ptr=buf, *ptrc=buf; while(*ptr) { if (!isspace(*ptr)) { *ptrc=*ptr; ptrc++; } ptr++; } *ptrc='\0'; return ptrc - buf; } MemoryContext * allocMemoryContext(MemoryContext* parent, int flags) { MemoryContext *res; res = (MemoryContext*)tmalloc( sizeof(MemoryContext) ); res->flags = flags; res->parent = parent; if ( parent ) { res->child = parent->child; parent->child = res; } else res->child = NULL; res->chunk = (MemoryChunk*)tmalloc( MEMCHNKHDRSZ + CNTXCHUNK ); res->chunk->size = res->chunk->freesize = CNTXCHUNK; res->chunk->next = NULL; return res; } void freeMemoryContext(MemoryContext *cntx) { MemoryContext *ptr=cntx; MemoryChunk *chunk, *chunkptr; if ( cntx->parent ) cntx->parent->child=NULL; while( ptr ) { cntx=ptr->child; chunkptr=ptr->chunk; while( chunkptr ) { chunk=chunkptr->next; tfree(chunkptr); chunkptr=chunk; } tfree(ptr); ptr=cntx; } } void resetMemoryContext(MemoryContext *cntx) { MemoryChunk *chunk, *chunkptr; while( cntx ) { chunkptr = cntx->chunk; chunkptr->freesize = chunkptr->size; chunkptr = chunkptr->next; cntx->chunk->next = NULL; while( chunkptr ) { chunk=chunkptr->next; tfree(chunkptr); chunkptr=chunk; } cntx=cntx->child; } } void* mcalloc(MemoryContext *cntx, size_t size) { MemoryChunk *chunk = cntx->chunk; MCAllocatedSpace *alloc; size = PTRALIGN(size) + MCASHDRSZ; if ( cntx->flags & MC_DEBUG ) size += sizeof(u_int32_t); if ( chunk->freesize < size ) { MemoryChunk *newchunk; if ( size >= CNTXCHUNK ) { newchunk = (MemoryChunk*)tmalloc(MEMCHNKHDRSZ + size); newchunk->size = newchunk->freesize = size; newchunk->next = chunk->next; chunk->next = newchunk; } else { newchunk = (MemoryChunk*)tmalloc(MEMCHNKHDRSZ + CNTXCHUNK); newchunk->size = newchunk->freesize = CNTXCHUNK; newchunk->next = chunk; cntx->chunk = newchunk; } chunk = newchunk; } alloc = (MCAllocatedSpace*)( chunk->data + chunk->size - chunk->freesize ); alloc->size = size; alloc->cntx = cntx; chunk->freesize -= size; if ( cntx->flags & MC_DEBUG ) { *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) = MCMAGICKNUMBER; memset( alloc->data, 0xc3, size - MCASHDRSZ - sizeof(u_int32_t) ); } return (void*)(alloc->data); } void * mc0alloc(MemoryContext *cntx, size_t size) { void *res = mcalloc(cntx, size); memset( res, 0, size ); return res; } void * mcrealloc(void * ptr, size_t size) { MCAllocatedSpace *alloc = (MCAllocatedSpace*)( (char*)ptr - MCASHDRSZ ); size_t realsize; if ( ptr==NULL ) tlog(TL_CRIT|TL_EXIT, "mcrealloc: realloc null pointer"); if ( alloc->cntx->flags & MC_DEBUG ) { tassert( *(u_int32_t*)( (char*)alloc + alloc->size - sizeof(u_int32_t) ) == MCMAGICKNUMBER ); realsize = alloc->size - MCASHDRSZ - sizeof(u_int32_t); } else realsize = alloc->size - MCASHDRSZ; if ( size > realsize ) { MemoryChunk *chunk = alloc->cntx->chunk; if ( (char*)alloc == chunk->data + chunk->size - chunk->freesize - alloc->size && PTRALIGN(size)-realsize <= alloc->cntx->chunk->freesize ) { /* just enlarge */ alloc->cntx->chunk->freesize -= PTRALIGN(size)-realsize; alloc->size+=PTRALIGN(size)-realsize; if ( alloc->cntx->flags & MC_DEBUG ) { memset( (char*)(alloc->data) + realsize, 0xc3, PTRALIGN(size)-realsize ); *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) = MCMAGICKNUMBER; } } else { void *newptr = mcalloc(alloc->cntx, size); memcpy( newptr, ptr, realsize ); ptr = newptr; if ( alloc->cntx->flags & MC_DEBUG ) memset( (char*)ptr + realsize, 0xc3, PTRALIGN(size)-realsize ); } } return ptr; } void mcfree(void * ptr) { MCAllocatedSpace *alloc = (MCAllocatedSpace*)( (char*)ptr - MCASHDRSZ ); MemoryChunk *chunk; if ( ptr==NULL ) tlog(TL_CRIT|TL_EXIT, "mcfree: free null pointer"); if ( alloc->cntx->flags & MC_DEBUG ) tassert( *(u_int32_t*)((char*)alloc + alloc->size - sizeof(u_int32_t) ) == MCMAGICKNUMBER ); chunk = alloc->cntx->chunk; if ( (char*)alloc == chunk->data + chunk->size - chunk->freesize - alloc->size ) /* last allocated value */ alloc->cntx->chunk->freesize+=alloc->size; alloc->cntx=NULL; } char * mcstrdup(MemoryContext *cntx, char * src) { return mcnstrdup(cntx, src, strlen(src)); } char * mcnstrdup(MemoryContext *cntx, char *src, int len) { char *dest=(char*)mcalloc(cntx, len+1); memcpy(dest, src, len); dest[len]='\0'; return dest; }