/* elmo - ELectronic Mail Operator Copyright (C) 2003 rzyjontko This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ---------------------------------------------------------------------- byte chunks allocation */ /**************************************************************************** * IMPLEMENTATION HEADERS ****************************************************************************/ #include #include #include #include "memblock.h" #include "xmalloc.h" #include "error.h" #include "debug.h" /**************************************************************************** * IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS ****************************************************************************/ #define MAX(a,b) (((a) > (b)) ? (a) : (b)) /**************************************************************************** * IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID) ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE DATA ****************************************************************************/ /**************************************************************************** * INTERFACE DATA ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES ****************************************************************************/ /**************************************************************************** * IMPLEMENTATION PRIVATE FUNCTIONS ****************************************************************************/ static memblock_t * resize (memblock_t *block, int size) { memblock_t *add; if (size > block->size - block->used){ debug_msg (DEBUG_INFO, "resizing block... used %d of %d bytes, need %d bytes", block->used, block->size, size); add = memblock_create (2 * MAX (block->size, size)); add->next = block; block = add; } return block; } static int get_len (const char *fmt, va_list ap) { int len = 0; char *str; while (*fmt){ if (*fmt == '%'){ switch (fmt[1]){ case 's': str = va_arg (ap, char *); len += strlen (str); fmt++; break; case 'd': va_arg (ap, int); len += 10; fmt++; break; case 'c': va_arg (ap, int); case '%': fmt++; break; } } fmt++; len++; } return len; } /**************************************************************************** * INTERFACE FUNCTIONS ****************************************************************************/ memblock_t * memblock_create (int size) { memblock_t *result = xmalloc (sizeof (memblock_t)); result->next = NULL; result->size = size; result->memptr = xmalloc (result->size); result->used = 0; result->last = 0; result->mark = -1; return result; } void memblock_destroy (memblock_t *block) { int i = 0; int size = 0; memblock_t *next; while (block){ size += block->size; next = block->next; xfree (block->memptr); xfree (block); block = next; i++; } debug_msg (DEBUG_INFO, "destroyed memblock length %d of total size %d", i, size); } char * memblock_strdup (memblock_t **block, const char *str) { int len; char *result; if (str == NULL || *block == NULL) return NULL; len = strlen (str) + 1; *block = resize (*block, len); result = (*block)->memptr + (*block)->used; memcpy ((*block)->memptr + (*block)->used, str, len); (*block)->used += len; (*block)->last = len; return result; } void * memblock_malloc (memblock_t **block, int size) { void *result; if (size == 0) return NULL; *block = resize (*block, size); result = (*block)->memptr + (*block)->used; (*block)->used += size; (*block)->last = size; return result; } void memblock_shrink_last (memblock_t *block, int size) { if (size > block->last) return; block->used -= size - block->last; block->last = size; } void memblock_free_last (memblock_t *block) { if (block == NULL) return; block->used -= block->last; block->last = 0; } void memblock_set_mark (memblock_t *block) { if (block == NULL) return; block->mark = block->used; } void memblock_free_marked (memblock_t **block) { memblock_t *next; while ((*block)->mark == -1){ next = (*block)->next; xfree ((*block)->memptr); xfree (*block); *block = next; } (*block)->used = (*block)->mark; } char * memblock_sprintf (memblock_t **block, const char *fmt, ...) { int len; char *result; va_list ap; va_start (ap, fmt); len = get_len (fmt, ap); va_end (ap); va_start (ap, fmt); result = memblock_malloc (block, len + 1); vsprintf (result, fmt, ap); va_end (ap); return result; } /**************************************************************************** * INTERFACE CLASS BODIES ****************************************************************************/ /**************************************************************************** * * END MODULE memblock.c * ****************************************************************************/