Blame bipbuffer.c

Packit 4e8bc4
/**
Packit 4e8bc4
 * Copyright (c) 2011, Willem-Hendrik Thiart
Packit 4e8bc4
 * Use of this source code is governed by a BSD-style license that can be
Packit 4e8bc4
 * found in the LICENSE.bipbuffer file.
Packit 4e8bc4
 *
Packit 4e8bc4
 * @file
Packit 4e8bc4
 * @author  Willem Thiart himself@willemthiart.com
Packit 4e8bc4
 */
Packit 4e8bc4
Packit 4e8bc4
#include "stdio.h"
Packit 4e8bc4
#include <stdlib.h>
Packit 4e8bc4
Packit 4e8bc4
/* for memcpy */
Packit 4e8bc4
#include <string.h>
Packit 4e8bc4
Packit 4e8bc4
#include "bipbuffer.h"
Packit 4e8bc4
Packit 4e8bc4
static size_t bipbuf_sizeof(const unsigned int size)
Packit 4e8bc4
{
Packit 4e8bc4
    return sizeof(bipbuf_t) + size;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
int bipbuf_unused(const bipbuf_t* me)
Packit 4e8bc4
{
Packit 4e8bc4
    if (1 == me->b_inuse)
Packit 4e8bc4
        /* distance between region B and region A */
Packit 4e8bc4
        return me->a_start - me->b_end;
Packit 4e8bc4
    else
Packit 4e8bc4
        return me->size - me->a_end;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
int bipbuf_size(const bipbuf_t* me)
Packit 4e8bc4
{
Packit 4e8bc4
    return me->size;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
int bipbuf_used(const bipbuf_t* me)
Packit 4e8bc4
{
Packit 4e8bc4
    return (me->a_end - me->a_start) + me->b_end;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
void bipbuf_init(bipbuf_t* me, const unsigned int size)
Packit 4e8bc4
{
Packit 4e8bc4
    me->a_start = me->a_end = me->b_end = 0;
Packit 4e8bc4
    me->size = size;
Packit 4e8bc4
    me->b_inuse = 0;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
bipbuf_t *bipbuf_new(const unsigned int size)
Packit 4e8bc4
{
Packit 4e8bc4
    bipbuf_t *me = malloc(bipbuf_sizeof(size));
Packit 4e8bc4
    if (!me)
Packit 4e8bc4
        return NULL;
Packit 4e8bc4
    bipbuf_init(me, size);
Packit 4e8bc4
    return me;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
void bipbuf_free(bipbuf_t* me)
Packit 4e8bc4
{
Packit 4e8bc4
    free(me);
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
int bipbuf_is_empty(const bipbuf_t* me)
Packit 4e8bc4
{
Packit 4e8bc4
    return me->a_start == me->a_end;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
/* find out if we should turn on region B
Packit 4e8bc4
 * ie. is the distance from A to buffer's end less than B to A? */
Packit 4e8bc4
static void __check_for_switch_to_b(bipbuf_t* me)
Packit 4e8bc4
{
Packit 4e8bc4
    if (me->size - me->a_end < me->a_start - me->b_end)
Packit 4e8bc4
        me->b_inuse = 1;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
/* TODO: DOCUMENT THESE TWO FUNCTIONS */
Packit 4e8bc4
unsigned char *bipbuf_request(bipbuf_t* me, const int size)
Packit 4e8bc4
{
Packit 4e8bc4
    if (bipbuf_unused(me) < size)
Packit 4e8bc4
        return 0;
Packit 4e8bc4
    if (1 == me->b_inuse)
Packit 4e8bc4
    {
Packit 4e8bc4
        return (unsigned char *)me->data + me->b_end;
Packit 4e8bc4
    }
Packit 4e8bc4
    else
Packit 4e8bc4
    {
Packit 4e8bc4
        return (unsigned char *)me->data + me->a_end;
Packit 4e8bc4
    }
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
int bipbuf_push(bipbuf_t* me, const int size)
Packit 4e8bc4
{
Packit 4e8bc4
    if (bipbuf_unused(me) < size)
Packit 4e8bc4
        return 0;
Packit 4e8bc4
Packit 4e8bc4
    if (1 == me->b_inuse)
Packit 4e8bc4
    {
Packit 4e8bc4
        me->b_end += size;
Packit 4e8bc4
    }
Packit 4e8bc4
    else
Packit 4e8bc4
    {
Packit 4e8bc4
        me->a_end += size;
Packit 4e8bc4
    }
Packit 4e8bc4
Packit 4e8bc4
    __check_for_switch_to_b(me);
Packit 4e8bc4
    return size;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
int bipbuf_offer(bipbuf_t* me, const unsigned char *data, const int size)
Packit 4e8bc4
{
Packit 4e8bc4
    /* not enough space */
Packit 4e8bc4
    if (bipbuf_unused(me) < size)
Packit 4e8bc4
        return 0;
Packit 4e8bc4
Packit 4e8bc4
    if (1 == me->b_inuse)
Packit 4e8bc4
    {
Packit 4e8bc4
        memcpy(me->data + me->b_end, data, size);
Packit 4e8bc4
        me->b_end += size;
Packit 4e8bc4
    }
Packit 4e8bc4
    else
Packit 4e8bc4
    {
Packit 4e8bc4
        memcpy(me->data + me->a_end, data, size);
Packit 4e8bc4
        me->a_end += size;
Packit 4e8bc4
    }
Packit 4e8bc4
Packit 4e8bc4
    __check_for_switch_to_b(me);
Packit 4e8bc4
    return size;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
unsigned char *bipbuf_peek(const bipbuf_t* me, const unsigned int size)
Packit 4e8bc4
{
Packit 4e8bc4
    /* make sure we can actually peek at this data */
Packit 4e8bc4
    if (me->size < me->a_start + size)
Packit 4e8bc4
        return NULL;
Packit 4e8bc4
Packit 4e8bc4
    if (bipbuf_is_empty(me))
Packit 4e8bc4
        return NULL;
Packit 4e8bc4
Packit 4e8bc4
    return (unsigned char *)me->data + me->a_start;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
unsigned char *bipbuf_peek_all(const bipbuf_t* me, unsigned int *size)
Packit 4e8bc4
{
Packit 4e8bc4
    if (bipbuf_is_empty(me))
Packit 4e8bc4
        return NULL;
Packit 4e8bc4
Packit 4e8bc4
    *size = me->a_end - me->a_start;
Packit 4e8bc4
    return (unsigned char*)me->data + me->a_start;
Packit 4e8bc4
}
Packit 4e8bc4
Packit 4e8bc4
unsigned char *bipbuf_poll(bipbuf_t* me, const unsigned int size)
Packit 4e8bc4
{
Packit 4e8bc4
    if (bipbuf_is_empty(me))
Packit 4e8bc4
        return NULL;
Packit 4e8bc4
Packit 4e8bc4
    /* make sure we can actually poll this data */
Packit 4e8bc4
    if (me->size < me->a_start + size)
Packit 4e8bc4
        return NULL;
Packit 4e8bc4
Packit 4e8bc4
    void *end = me->data + me->a_start;
Packit 4e8bc4
    me->a_start += size;
Packit 4e8bc4
Packit 4e8bc4
    /* we seem to be empty.. */
Packit 4e8bc4
    if (me->a_start == me->a_end)
Packit 4e8bc4
    {
Packit 4e8bc4
        /* replace a with region b */
Packit 4e8bc4
        if (1 == me->b_inuse)
Packit 4e8bc4
        {
Packit 4e8bc4
            me->a_start = 0;
Packit 4e8bc4
            me->a_end = me->b_end;
Packit 4e8bc4
            me->b_end = me->b_inuse = 0;
Packit 4e8bc4
        }
Packit 4e8bc4
        else
Packit 4e8bc4
            /* safely move cursor back to the start because we are empty */
Packit 4e8bc4
            me->a_start = me->a_end = 0;
Packit 4e8bc4
    }
Packit 4e8bc4
Packit 4e8bc4
    __check_for_switch_to_b(me);
Packit 4e8bc4
    return end;
Packit 4e8bc4
}