/*
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 <string.h>
#include <stdarg.h>
#include <stdio.h>
#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
*
****************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1