410 lines
6.7 KiB
C
410 lines
6.7 KiB
C
/*
|
|
Copyright (C) 2009 - 2010
|
|
|
|
Artem Makhutov <artem@makhutov.org>
|
|
http://www.makhutov.org
|
|
|
|
Dmitry Vagin <dmitry2004@yandex.ru>
|
|
*/
|
|
#include "ast_config.h"
|
|
|
|
#include "memmem.h"
|
|
#include <string.h> /* memchr() */
|
|
|
|
#include "ringbuffer.h"
|
|
|
|
EXPORT_DEF int rb_memcmp (const struct ringbuffer* rb, const char* mem, size_t len)
|
|
{
|
|
size_t tmp;
|
|
|
|
if (rb->used > 0 && len > 0 && rb->used >= len)
|
|
{
|
|
if ((rb->read + len) > rb->size)
|
|
{
|
|
tmp = rb->size - rb->read;
|
|
if (memcmp (rb->buffer + rb->read, mem, tmp) == 0)
|
|
{
|
|
len -= tmp;
|
|
mem += tmp;
|
|
|
|
if (memcmp (rb->buffer, mem, len) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (memcmp (rb->buffer + rb->read, mem, len) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* ============================ READ ============================= */
|
|
EXPORT_DEF int rb_read_all_iov (const struct ringbuffer* rb, struct iovec iov[2])
|
|
{
|
|
if (rb->used > 0)
|
|
{
|
|
if ((rb->read + rb->used) > rb->size)
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = rb->size - rb->read;
|
|
iov[1].iov_base = rb->buffer;
|
|
iov[1].iov_len = rb->used - iov[0].iov_len;
|
|
return 2;
|
|
}
|
|
else
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = rb->used;
|
|
iov[1].iov_len = 0;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT_DEF int rb_read_n_iov (const struct ringbuffer* rb, struct iovec iov[2], size_t len)
|
|
{
|
|
if (rb->used < len)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (len > 0)
|
|
{
|
|
if ((rb->read + len) > rb->size)
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = rb->size - rb->read;
|
|
iov[1].iov_base = rb->buffer;
|
|
iov[1].iov_len = len - iov[0].iov_len;
|
|
return 2;
|
|
}
|
|
else
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = len;
|
|
iov[1].iov_len = 0;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT_DEF int rb_read_until_char_iov (const struct ringbuffer* rb, struct iovec iov[2], char c)
|
|
{
|
|
void* p;
|
|
|
|
if (rb->used > 0)
|
|
{
|
|
if ((rb->read + rb->used) > rb->size)
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = rb->size - rb->read;
|
|
if ((p = memchr (iov[0].iov_base, c, iov[0].iov_len)) != NULL)
|
|
{
|
|
iov[0].iov_len = p - iov[0].iov_base;
|
|
iov[1].iov_len = 0;
|
|
return 1;
|
|
}
|
|
|
|
if ((p = memchr (rb->buffer, c, rb->used - iov[0].iov_len)) != NULL)
|
|
{
|
|
iov[1].iov_base = rb->buffer;
|
|
iov[1].iov_len = p - rb->buffer;
|
|
return 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = rb->used;
|
|
if ((p = memchr (iov[0].iov_base, c, iov[0].iov_len)) != NULL)
|
|
{
|
|
iov[0].iov_len = p - iov[0].iov_base;
|
|
iov[1].iov_len = 0;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT_DEF int rb_read_until_mem_iov (const struct ringbuffer* rb, struct iovec iov[2], const void* mem, size_t len)
|
|
{
|
|
size_t i;
|
|
void* p;
|
|
|
|
if (len == 1)
|
|
{
|
|
return rb_read_until_char_iov (rb, iov, *((char*) mem));
|
|
}
|
|
|
|
if (rb->used > 0 && len > 0 && rb->used >= len)
|
|
{
|
|
if ((rb->read + rb->used) > rb->size)
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = rb->size - rb->read;
|
|
if (iov[0].iov_len >= len)
|
|
{
|
|
if ((p = memmem (iov[0].iov_base, iov[0].iov_len, mem, len)) != NULL)
|
|
{
|
|
iov[0].iov_len = p - iov[0].iov_base;
|
|
iov[1].iov_len = 0;
|
|
return 1;
|
|
}
|
|
|
|
i = 1;
|
|
iov[1].iov_base = iov[0].iov_base + iov[0].iov_len - len + 1;
|
|
}
|
|
else
|
|
{
|
|
i = len - iov[0].iov_len;
|
|
iov[1].iov_base = iov[0].iov_base;
|
|
}
|
|
|
|
|
|
while (i < len)
|
|
{
|
|
if (memcmp (iov[1].iov_base, mem, len - i) == 0 && memcmp (rb->buffer, mem + i, i) == 0)
|
|
{
|
|
iov[0].iov_len = iov[1].iov_base - iov[0].iov_base;
|
|
iov[1].iov_len = 0;
|
|
return 1;
|
|
}
|
|
|
|
if (rb->used == iov[0].iov_len + i)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
iov[1].iov_base++;
|
|
i++;
|
|
}
|
|
|
|
if (rb->used >= iov[0].iov_len + len)
|
|
{
|
|
if ((p = memmem (rb->buffer, rb->used - iov[0].iov_len, mem, len)) != NULL)
|
|
{
|
|
if (p == rb->buffer)
|
|
{
|
|
iov[1].iov_len = 0;
|
|
return 1;
|
|
}
|
|
|
|
iov[1].iov_base = rb->buffer;
|
|
iov[1].iov_len = p - rb->buffer;
|
|
return 2;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->read;
|
|
iov[0].iov_len = rb->used;
|
|
if ((p = memmem (iov[0].iov_base, iov[0].iov_len, mem, len)) != NULL)
|
|
{
|
|
iov[0].iov_len = p - iov[0].iov_base;
|
|
iov[1].iov_len = 0;
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT_DEF size_t rb_read_upd (struct ringbuffer* rb, size_t len)
|
|
{
|
|
size_t s;
|
|
|
|
if (rb->used < len)
|
|
{
|
|
len = rb->used;
|
|
}
|
|
|
|
if (len > 0)
|
|
{
|
|
rb->used -= len;
|
|
|
|
if (rb->used == 0)
|
|
{
|
|
rb->read = 0;
|
|
rb->write = 0;
|
|
}
|
|
else
|
|
{
|
|
s = rb->read + len;
|
|
|
|
if (s >= rb->size)
|
|
{
|
|
rb->read = s - rb->size;
|
|
}
|
|
else
|
|
{
|
|
rb->read = s;
|
|
}
|
|
}
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
/* unused
|
|
static size_t rb_read (struct ringbuffer* rb, char* buf, size_t len)
|
|
{
|
|
size_t s;
|
|
|
|
if (rb->used < len)
|
|
{
|
|
len = rb->used;
|
|
}
|
|
|
|
if (len > 0)
|
|
{
|
|
s = rb->read + len;
|
|
if (s > rb->size)
|
|
{
|
|
memmove (buf, rb->buffer + rb->read, rb->size - rb->read);
|
|
memmove (buf + rb->size - rb->read, rb->buffer, s - rb->size);
|
|
rb->read = s - rb->size;
|
|
}
|
|
else
|
|
{
|
|
memmove (buf, rb->buffer + rb->read, len);
|
|
if (s == rb->size)
|
|
{
|
|
rb->read = 0;
|
|
}
|
|
else
|
|
{
|
|
rb->read = s;
|
|
}
|
|
}
|
|
|
|
rb->used -= len;
|
|
|
|
if (rb->used == 0)
|
|
{
|
|
rb->read = 0;
|
|
rb->write = 0;
|
|
}
|
|
}
|
|
|
|
return len;
|
|
}
|
|
*/
|
|
|
|
/* ============================ WRITE ============================ */
|
|
|
|
EXPORT_DEF int rb_write_iov (const struct ringbuffer* rb, struct iovec iov[2])
|
|
{
|
|
size_t free;
|
|
|
|
free = rb_free (rb);
|
|
if (free > 0)
|
|
{
|
|
if ((rb->write + free) > rb->size)
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->write;
|
|
iov[0].iov_len = rb->size - rb->write;
|
|
iov[1].iov_base = rb->buffer;
|
|
iov[1].iov_len = free - iov[0].iov_len;
|
|
|
|
return 2;
|
|
}
|
|
else
|
|
{
|
|
iov[0].iov_base = rb->buffer + rb->write;
|
|
iov[0].iov_len = free;
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT_DEF size_t rb_write_upd (struct ringbuffer* rb, size_t len)
|
|
{
|
|
size_t free;
|
|
size_t s;
|
|
|
|
free = rb_free (rb);
|
|
if (free < len)
|
|
{
|
|
len = free;
|
|
}
|
|
|
|
if (len > 0)
|
|
{
|
|
s = rb->write + len;
|
|
|
|
if (s > rb->size)
|
|
{
|
|
rb->write = s - rb->size;
|
|
}
|
|
else
|
|
{
|
|
rb->write = s;
|
|
}
|
|
|
|
rb->used += len;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
EXPORT_DEF size_t rb_write_core (struct ringbuffer* rb, const char* buf, size_t len, rb_write_f method)
|
|
{
|
|
size_t free;
|
|
size_t s;
|
|
|
|
free = rb_free (rb);
|
|
if (free < len)
|
|
{
|
|
len = free;
|
|
}
|
|
|
|
if (len > 0)
|
|
{
|
|
s = rb->write + len;
|
|
|
|
if (s > rb->size)
|
|
{
|
|
(*method) (rb->buffer + rb->write, buf, rb->size - rb->write);
|
|
(*method) (rb->buffer, buf + rb->size - rb->write, s - rb->size);
|
|
rb->write = s - rb->size;
|
|
}
|
|
else
|
|
{
|
|
(*method) (rb->buffer + rb->write, buf, len);
|
|
if (s == rb->size)
|
|
{
|
|
rb->write = 0;
|
|
}
|
|
else
|
|
{
|
|
rb->write = s;
|
|
}
|
|
}
|
|
|
|
rb->used += len;
|
|
}
|
|
|
|
return len;
|
|
}
|