diff options
author | Denis Kenzior <denis.kenzior@intel.com> | 2009-05-06 14:33:17 -0700 |
---|---|---|
committer | Marcel Holtmann <marcel.holtmann@intel.com> | 2009-05-06 14:42:54 -0700 |
commit | 64c42764736de15544e58666bdf97de088f7a7b5 (patch) | |
tree | 8f496fa6822a15acc593bd8ee66007ed0925efd3 /gatchat/ringbuffer.c | |
parent | 4ea27466bf3a5a3309d5ee689a1470c20c483ef9 (diff) | |
download | ofono-64c42764736de15544e58666bdf97de088f7a7b5.tar.bz2 |
Add AT chat library implementation
Diffstat (limited to 'gatchat/ringbuffer.c')
-rw-r--r-- | gatchat/ringbuffer.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/gatchat/ringbuffer.c b/gatchat/ringbuffer.c new file mode 100644 index 00000000..0b1860f4 --- /dev/null +++ b/gatchat/ringbuffer.c @@ -0,0 +1,199 @@ +/* + * + * AT chat library with GLib integration + * + * Copyright (C) 2008-2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> + +#include <glib.h> + +#include "ringbuffer.h" + +#define MAX_SIZE 262144 + +struct ring_buffer *ring_buffer_new(unsigned int size) +{ + unsigned int real_size = 1; + struct ring_buffer *buffer; + + /* Find the next power of two for size */ + while (real_size < size && real_size < MAX_SIZE) + real_size = real_size << 1; + + if (real_size > MAX_SIZE) + return NULL; + + buffer = g_new(struct ring_buffer, 1); + + if (!buffer) + return NULL; + + buffer->buffer = g_new(unsigned char, real_size); + + if (!buffer->buffer) { + g_free(buffer); + return NULL; + } + + buffer->size = real_size; + buffer->in = 0; + buffer->out = 0; + + return buffer; +} + +int ring_buffer_write(struct ring_buffer *buf, const void *data, + unsigned int len) +{ + unsigned int end; + unsigned int offset; + const unsigned char *d = data; /* Needed to satisfy non-gcc compilers */ + + /* Determine how much we can actually write */ + len = MIN(len, buf->size - buf->in + buf->out); + + /* Determine how much to write before wrapping */ + offset = buf->in % buf->size; + end = MIN(len, buf->size - offset); + memcpy(buf->buffer+offset, d, end); + + /* Now put the remainder on the beginning of the buffer */ + memcpy(buf->buffer, d + end, len - end); + + buf->in += len; + + return len; +} + +unsigned char *ring_buffer_write_ptr(struct ring_buffer *buf) +{ + return buf->buffer + buf->in % buf->size; +} + +int ring_buffer_avail_no_wrap(struct ring_buffer *buf) +{ + unsigned int offset = buf->in % buf->size; + unsigned int len = buf->size - buf->in + buf->out; + + return MIN(len, buf->size - offset); +} + +int ring_buffer_write_advance(struct ring_buffer *buf, unsigned int len) +{ + len = MIN(len, buf->size - buf->in + buf->out); + buf->in += len; + + return len; +} + +int ring_buffer_read(struct ring_buffer *buf, void *data, unsigned int len) +{ + unsigned int end; + unsigned int offset; + unsigned char *d = data; + + len = MIN(len, buf->in - buf->out); + + /* Grab data from buffer starting at offset until the end */ + offset = buf->out % buf->size; + end = MIN(len, buf->size - offset); + memcpy(d, buf->buffer + offset, end); + + /* Now grab remainder from the beginning */ + memcpy(d + end, buf->buffer, len - end); + + buf->out += len; + + if (buf->out == buf->in) + buf->out = buf->in = 0; + + return len; +} + +int ring_buffer_drain(struct ring_buffer *buf, unsigned int len) +{ + len = MIN(len, buf->in - buf->out); + + buf->out += len; + + if (buf->out == buf->in) + buf->out = buf->in = 0; + + return len; +} + +int ring_buffer_len_no_wrap(struct ring_buffer *buf) +{ + unsigned int offset = buf->out % buf->size; + unsigned int len = buf->in - buf->out; + + return MIN(len, buf->size - offset); +} + +unsigned char *ring_buffer_read_ptr(struct ring_buffer *buf, + unsigned int offset) +{ + return buf->buffer + (buf->out + offset) % buf->size; +} + +int ring_buffer_len(struct ring_buffer *buf) +{ + if (!buf) + return -1; + + return buf->in - buf->out; +} + +void ring_buffer_reset(struct ring_buffer *buf) +{ + if (!buf) + return; + + buf->in = 0; + buf->out = 0; +} + +int ring_buffer_avail(struct ring_buffer *buf) +{ + if (!buf) + return -1; + + return buf->size - buf->in + buf->out; +} + +int ring_buffer_capacity(struct ring_buffer *buf) +{ + if (!buf) + return -1; + + return buf->size; +} + +void ring_buffer_free(struct ring_buffer *buf) +{ + if (!buf) + return; + + g_free(buf->buffer); + g_free(buf); +} |