#include "ringbuffer.h"
#include "string.h"

uint8_t rb_init(RingBufferHandleTypedef* self, uint8_t* buffdata, uint32_t bufflen) reentrant
{
    if (self == NULL || buffdata == NULL || bufflen == 0)
	{
        return 0;
    }
	self->buf= buffdata;
	self->len = bufflen;
	self->w_ptr = 0;
	self->r_ptr = 0;
	return 1;

}

uint32_t rb_getfree(const RingBufferHandleTypedef* self) reentrant
{
	uint32_t len = 0;
	uint32_t w_ptr =0;
	uint32_t r_ptr =0;
	
	if(!BUF_IS_VALID(self))
	{
		return 0;
	}
	
	w_ptr = self->w_ptr;
	r_ptr = self->r_ptr;
	
	if(w_ptr >= r_ptr)
	{
		len = self->len - (w_ptr - r_ptr);
	}
	else
	{
		len = r_ptr - w_ptr;
	}
	return len;
}

uint32_t rb_getfull(const RingBufferHandleTypedef* self) reentrant
{
	uint32_t len = 0;
	uint32_t w_ptr =0;
	uint32_t r_ptr =0;
	
	if(!BUF_IS_VALID(self))
	{
		return 0;
	}
	
	w_ptr = self->w_ptr;
	r_ptr = self->r_ptr;
	
	if(w_ptr >= r_ptr)
	{
		len = w_ptr - r_ptr;
	}
	else
	{
		len = self->len - (r_ptr - w_ptr);
	}
	return len;
}


static uint32_t _rb_write(RingBufferHandleTypedef* self, uint8_t* buf, uint32_t btw) reentrant
{

	uint32_t free = 0; 
	uint32_t w_ptr = 0;
	uint32_t copy_len = 0;
	
    if (!BUF_IS_VALID(self) || buf == NULL || btw == 0)
	{
        return 0;
    }
	
	free = rb_getfree(self);
	
	if(free == 0)
	{
		return 0;
	}
	
	btw = BUF_MIN(free, btw);
	w_ptr = self->w_ptr;
	copy_len = BUF_MIN(self->len - w_ptr, btw);
	memcpy(&self->buf[w_ptr], buf, (uint16_t)copy_len);
	buf += copy_len;
	w_ptr+= copy_len;
	btw -=copy_len;
	if(btw > 0)
	{
		memcpy(self->buf, buf, (uint16_t)btw);
		w_ptr = btw;
	}
	
	if(w_ptr >= self->len)
	{
		w_ptr = 0;
	}
	
	self->w_ptr = w_ptr;
	self->write_len = copy_len + btw;
	return 1;
}

uint32_t rb_write(RingBufferHandleTypedef* self, uint8_t* buf, uint32_t btw) reentrant
{
	self->write_len = 0;
	if(_rb_write(self, buf, btw))
	{
		return self->write_len;
	}
	return 0;
}



static uint32_t _rb_read(RingBufferHandleTypedef* self, uint8_t* buf, uint32_t btr) reentrant
{

	uint32_t full = 0; 
	uint32_t r_ptr = 0;
	uint32_t copy_len = 0;
	
    if (!BUF_IS_VALID(self) || buf == NULL || btr == 0)
	{
        return 0;
    }
	
	full = rb_getfull(self);
	
	if(full == 0)
	{
		return 0;
	}
	
	btr = BUF_MIN(full, btr);
	r_ptr = self->r_ptr;
	copy_len = BUF_MIN(self->len - r_ptr, btr);
	memcpy(buf, &self->buf[r_ptr], (uint16_t)copy_len);
	buf += copy_len;
	r_ptr+= copy_len;
	btr -=copy_len;
	if(btr > 0)
	{
		memcpy(buf, self->buf, (uint16_t)btr);
		r_ptr = btr;
	}
	
	if(r_ptr >= self->len)
	{
		r_ptr = 0;
	}
	
	self->r_ptr = r_ptr;
	self->read_len = copy_len + btr;
	return 1;
}

uint32_t rb_read(RingBufferHandleTypedef* self, uint8_t* buf, uint32_t btr) reentrant
{
	self->read_len = 0;
	if(_rb_read(self, buf, btr))
	{
		return self->read_len;
	}
	return 0;
}