/* 
   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.  

   ----------------------------------------------------------------------

*/
/****************************************************************************
 *    IMPLEMENTATION HEADERS
 ****************************************************************************/

#include <string.h>
#include <stdio.h>
#include <errno.h>

#include "memchunk.h"
#include "xmalloc.h"
#include "memblock.h"
#include "misc.h"
#include "error.h"

/****************************************************************************
 *    IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS
 ****************************************************************************/
/****************************************************************************
 *    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 void
realloc_for (memchunk_t *chunk, int len)
{
        if (chunk->used + len < chunk->size)
                return;

        while (chunk->used + len >= chunk->size)
                chunk->size *= 2;

        chunk->memptr = xrealloc (chunk->memptr, chunk->size);
}

/****************************************************************************
 *    INTERFACE FUNCTIONS
 ****************************************************************************/

memchunk_t *
memchunk_create_size (int size)
{
        memchunk_t *result = xmalloc (sizeof (memchunk_t));

        result->size   = size;
        result->used   = 0;
        result->memptr = xmalloc (size);

        return result;
}




void
memchunk_memcpy (memchunk_t *memchunk, const void *src, int len)
{
        realloc_for (memchunk, len);

        memcpy (memchunk->memptr + memchunk->used, src, len);
        memchunk->used += len;
}



void
memchunk_strcpy (memchunk_t *memchunk, const char *str)
{
        int len = strlen (str);

        memchunk_memcpy (memchunk, str, len);
}



void
memchunk_intdump (memchunk_t *memchunk, int a)
{
        memchunk_memcpy (memchunk, &a, sizeof (a));
}


void
memchunk_strdump (memchunk_t *memchunk, const char *str)
{
        int len = (str) ? (strlen (str) + 1) : 0;

        memchunk_memcpy (memchunk, &len, sizeof (len));
        memchunk_memcpy (memchunk, str, len);
}



void
memchunk_reset (memchunk_t *memchunk)
{
        memchunk->used = 0;
}



void
memchunk_resize_to (memchunk_t *memchunk, int desired_size)
{
        if (memchunk->size >= desired_size)
                return;

        memchunk->size   = desired_size;
        memchunk->memptr = xrealloc (memchunk->memptr, desired_size);
}


int
memchunk_data_size (memchunk_t *memchunk)
{
        return memchunk->used;
}



void
memchunk_destroy (memchunk_t *memchunk)
{
        xfree (memchunk->memptr);
        xfree (memchunk);
}



void
memchunk_rewind (memchunk_t *memchunk)
{
        memchunk->pos = 0;
}



int
memchunk_intget (memchunk_t *memchunk)
{
        int result;

        memcpy (&result, memchunk->memptr + memchunk->pos, sizeof (result));
        memchunk->pos += sizeof (result);
        return result;
}



char *
memchunk_strget (memchunk_t *memchunk)
{
        int   len;
        char *result;

        len    = memchunk_intget (memchunk);
        result = xmalloc (len);
        memcpy (result, memchunk->memptr + memchunk->pos, len);
        memchunk->pos += len;

        return result;
}



char *
memchunk_strget_memblock (memchunk_t *memchunk, memblock_t **memblock)
{
        int   len;
        char *result;

        len    = memchunk_intget (memchunk);
        result = memblock_malloc (memblock, len);
        memcpy (result, memchunk->memptr + memchunk->pos, len);
        memchunk->pos += len;

        return result;
}



int
memchunk_dump (memchunk_t *chunk, FILE *fp)
{
        if (fwrite (& (chunk->used), sizeof (int), 1, fp) != 1
            || fwrite (chunk->memptr, 1, chunk->used, fp) != chunk->used){
                error_ (errno, "fwrite");
                fclose (fp);
                return 1;
        }
        return 0;
}



int
memchunk_read (memchunk_t *chunk, FILE *fp)
{
        int chunk_size;

        if (fread (&chunk_size, sizeof (chunk_size), 1, fp) != 1){
                error_ (errno, "fread");
                fclose (fp);
                return 1;
        }
        memchunk_resize_to (chunk, chunk_size);
        if (fread (chunk->memptr, chunk_size, 1, fp) != 1){
                error_ (errno, "fread");
                fclose (fp);
                return 1;
        }

        memchunk_rewind (chunk);

        return 0;
}

/****************************************************************************
 *    INTERFACE CLASS BODIES
 ****************************************************************************/
/****************************************************************************
 *
 *    END MODULE memchunk.c
 *
 ****************************************************************************/


syntax highlighted by Code2HTML, v. 0.9.1