#include <sys/queue.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include "int.h"
int
vring_alloc(struct virtual_ring *pvr, size_t size)
{
if (pvr->buf_start != NULL)
return (EBUSY);
pvr->buf_start = malloc(size);
if (pvr->buf_start == NULL)
return (ENOMEM);
pvr->pos_read = 0;
pvr->total_size = size;
pvr->len_write = 0;
return (0);
}
void
vring_free(struct virtual_ring *pvr)
{
if (pvr->buf_start != NULL) {
free(pvr->buf_start);
pvr->buf_start = NULL;
}
}
void
vring_reset(struct virtual_ring *pvr)
{
pvr->pos_read = 0;
pvr->len_write = 0;
}
void
vring_get_read(struct virtual_ring *pvr, uint8_t **pptr, size_t *plen)
{
uint32_t delta;
if (pvr->buf_start == NULL) {
*pptr = NULL;
*plen = 0;
return;
}
delta = pvr->total_size - pvr->pos_read;
if (delta > pvr->len_write)
delta = pvr->len_write;
*pptr = pvr->buf_start + pvr->pos_read;
*plen = delta;
}
void
vring_get_write(struct virtual_ring *pvr, uint8_t **pptr, size_t *plen)
{
uint32_t delta;
uint32_t len_read;
uint32_t pos_write;
if (pvr->buf_start == NULL) {
*pptr = NULL;
*plen = 0;
return;
}
pos_write = pvr->pos_read + pvr->len_write;
if (pos_write >= pvr->total_size)
pos_write -= pvr->total_size;
len_read = pvr->total_size - pvr->len_write;
delta = pvr->total_size - pos_write;
if (delta > len_read)
delta = len_read;
*pptr = pvr->buf_start + pos_write;
*plen = delta;
}
void
vring_inc_read(struct virtual_ring *pvr, size_t len)
{
pvr->pos_read += len;
pvr->len_write -= len;
if (pvr->pos_read == pvr->total_size)
pvr->pos_read = 0;
}
void
vring_inc_write(struct virtual_ring *pvr, size_t len)
{
pvr->len_write += len;
}
size_t
vring_total_read_len(struct virtual_ring *pvr)
{
return (pvr->len_write);
}
size_t
vring_total_write_len(struct virtual_ring *pvr)
{
return (pvr->total_size - pvr->len_write);
}
size_t
vring_write_linear(struct virtual_ring *pvr, const uint8_t *src, size_t total)
{
uint8_t *buf_ptr;
size_t buf_len;
size_t sum = 0;
while (total != 0) {
vring_get_write(pvr, &buf_ptr, &buf_len);
if (buf_len == 0)
break;
if (buf_len > total)
buf_len = total;
memcpy(buf_ptr, src, buf_len);
vring_inc_write(pvr, buf_len);
src += buf_len;
sum += buf_len;
total -= buf_len;
}
return (sum);
}
size_t
vring_read_linear(struct virtual_ring *pvr, uint8_t *dst, size_t total)
{
uint8_t *buf_ptr;
size_t buf_len;
size_t sum = 0;
if (total > vring_total_read_len(pvr))
return (0);
while (total != 0) {
vring_get_read(pvr, &buf_ptr, &buf_len);
if (buf_len == 0)
break;
if (buf_len > total)
buf_len = total;
memcpy(dst, buf_ptr, buf_len);
vring_inc_read(pvr, buf_len);
dst += buf_len;
sum += buf_len;
total -= buf_len;
}
return (sum);
}
size_t
vring_write_zero(struct virtual_ring *pvr, size_t total)
{
uint8_t *buf_ptr;
size_t buf_len;
size_t sum = 0;
while (total != 0) {
vring_get_write(pvr, &buf_ptr, &buf_len);
if (buf_len == 0)
break;
if (buf_len > total)
buf_len = total;
memset(buf_ptr, 0, buf_len);
vring_inc_write(pvr, buf_len);
sum += buf_len;
total -= buf_len;
}
return (sum);
}