/* IRCfs - IRC FileServ for *nix. * Copyright (C) 2002 Nick 'Zaf' Clifford * For licensing details, refer to the LICENSE file in the source * code directory. */ #include "pool.h" #include "runtime.h" #include "select.h" #ifdef POOL_MAINTAINANCE struct _filepos { unsigned int line; const char *filename; time_t when; }; #endif struct pool { unsigned int magic; void *mem,*base; size_t size; struct pool *children; struct pool *parent; struct pool *next_sibling; #ifdef POOL_MAINTAINANCE struct _filepos allocated,destroyed; struct mem_header *last_header; #endif }; #ifdef POOL_MAINTAINANCE struct mem_header { size_t size; struct _filepos allocated; } #endif static void pool_clean_tmp(); POOL tmp_pool=NULL; POOL pool_new_n(POOL parent, size_t size) { struct pool *p; size_t s; void *ptr; ASSERT(size != 0); s = size + sizeof(struct pool); /* increment to next 64k block */ s += 64-(s%64); ptr = malloc(s); p = (struct pool *) ptr; memset(p,0,s); p->magic = POOL_MAGIC; p->base = ptr; p->mem = ptr + sizeof(struct pool); p->size = s; p->parent = NULL; p->next_sibling = NULL; p->children = NULL; if (parent) { p->parent = parent; p->next_sibling = parent->children; parent->children = p; } return p; } void pool_destroy(POOL p) { p->magic = 0; free(p); } static void pool_clean_tmp() { if (!tmp_pool) return; pool_destroy(tmp_pool); } void *tmp_alloc(size_t size) { if (tmp_pool == NULL) { tmp_pool = pool_new_n(NULL,POOL_TMP_SIZE); if (tmp_pool == NULL) return NULL; register_pre_func(pool_clean_tmp); } return palloc(tmp_pool,size); } char *tmp_strdup(const char *str) { size_t len; char *cp; ASSERT(str); len = strlen(str); cp = tmp_alloc(len+1); if (cp) strcpy(cp,str); return cp; } char *tmp_strdupn(const char *str,size_t n) { register size_t len; register const char *c; char *cp; ASSERT(n >= 0); c = str; while(*c != 0 && len < n) { c++; len++; } cp = tmp_alloc(len+1); if (cp) strcpy(cp,str); return cp; } char *pstrdupn(POOL p, const char *str,size_t n) { register size_t len; register const char *c; char *cp; ASSERT(p); ASSERT(str); ASSERT(n >= 0); c = str; while(*c != 0 && len < n) { c++; len++; } cp = palloc(p,len+1); if (cp) strcpy(cp,str); return cp; } char *pstrdup(POOL p, const char *str) { size_t len; char *cp; ASSERT(p); ASSERT(str); len = strlen(str); cp = palloc(p,len+1); if (cp) strcpy(cp,str); return cp; } void *palloc(struct pool *p, size_t size) { POOL pc; void *r; size_t left; left = p->size - (p->mem - p->base); if (size > left) { /* Not enough memory in this block */ /* Search children for memory */ for (pc = p->children; pc != NULL; pc=pc->next_sibling) { left = pc->size - (pc->mem - (void *)pc); if (size <= left) break; } if (pc == NULL) { /* Not enough memory in any children blocks either */ pc = pool_new_n(p,size + p->size); } return palloc(pc,size); } r = p->mem; p->mem += size; return r; }