/* * 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 #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; } /*********StringBuffer********/ static inline void* StringBufferAlloc(StringBuffer* state, void *ptr, size_t size) { if (state->mc) return (ptr) ? mcrealloc(ptr, size) : mcalloc(state->mc, size); else if (state->memalloc) return state->memalloc(ptr, size); else return (ptr) ? trealloc(ptr, size) : tmalloc(size); } static StringBuffer* initStringBufferInternal(StringBuffer* state, int initsize) { state->len = (initsize>0) ? initsize : 1024; state->ptr = state->buf = (char*)StringBufferAlloc(state, NULL, initsize); if (!state->ptr) return NULL; *(state->ptr) ='\0'; return state; } StringBuffer* initStringBuffer(StringBuffer* state, int initsize) { memset(state, 0, sizeof(*state)); return initStringBufferInternal(state, initsize); } StringBuffer* initStringBufferMC(StringBuffer* state, MemoryContext *mc, int initsize) { memset(state, 0, sizeof(*state)); state->mc = mc; return initStringBufferInternal(state, initsize); } StringBuffer* initStringBufferMA(StringBuffer* state, MemAlloc memalloc, int initsize) { memset(state, 0, sizeof(*state)); state->memalloc = memalloc; return initStringBufferInternal(state, initsize); } StringBuffer* appendStringBuffer( StringBuffer *state, char *string, int stringlen) { if ( string ) { if ( stringlen <= 0 ) stringlen = strlen(string); } else stringlen = 0; if ( stringlen == 0 ) return state; while ( state->len - ( state->ptr - state->buf ) < stringlen + 1 ) { int diff = state->ptr - state->buf; state->len *= 2; state->buf = (char*)StringBufferAlloc(state, state->buf, state->len); state->ptr = state->buf + diff; } memcpy(state->ptr, string, stringlen); state->ptr += stringlen; *state->ptr = '\0'; return state; } StringBuffer* printStringBuffer( StringBuffer *state, const char *format, ...) { va_list args; int printedlen; int buffreelen; buffreelen = state->len - ( state->ptr - state->buf ) - 1; va_start(args, format); printedlen = vsnprintf(state->ptr, buffreelen, format, args); va_end(args); /* * if buffer too short, resize buffer and * print it again */ if ( buffreelen<=printedlen ) { u_int32_t curlen = state->ptr - state->buf; do { state->len *= 2; } while( state->ptr - state->buf + printedlen >= state->len ); state->buf = (char*)StringBufferAlloc(state, state->buf, state->len); state->ptr = state->buf + curlen; va_start(args, format); printedlen = vsnprintf(state->ptr, printedlen+1, format, args); va_end(args); } state->ptr += printedlen; return state; }