#include "ring.h"

//------------------------------------------------------------------------------

void rb_init(ring_buffer_t* rb)
{
    rb->head = 0;
    rb->tail = 0;
}

//------------------------------------------------------------------------------

bool rb_push(ring_buffer_t* rb, uint8_t data)
{
    uint16_t next = (rb->head + 1) & (RB_SIZE - 1);

    if (next == rb->tail)
        return false; // buffer full

    rb->buffer[rb->head] = data;
    rb->head = next;
    return true;
}

//------------------------------------------------------------------------------

bool rb_pop(ring_buffer_t* rb, uint8_t* data)
{
    if (rb->head == rb->tail)
        return false; // empty

    *data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) & (RB_SIZE - 1);
    return true;
}

//------------------------------------------------------------------------------

uint16_t rb_available(const ring_buffer_t* rb)
{
    return (rb->head - rb->tail) & (RB_SIZE - 1);
}

//------------------------------------------------------------------------------

bool rb_peek(const ring_buffer_t* const rb, uint8_t* const data)
{
    if (rb->head == rb->tail)
        return false; // empty

    *data = rb->buffer[rb->tail];
    return true;
}

//------------------------------------------------------------------------------

bool rb_peek_at(const ring_buffer_t* const rb, uint16_t index, uint8_t* data)
{
    if (index >= rb_available(rb))
        return false; // not enough data

    uint16_t pos = (rb->tail + index) & (RB_SIZE - 1);
    *data = rb->buffer[pos];

    return true;
}