summaryrefslogtreecommitdiffstats
path: root/gatchat/ringbuffer.c
diff options
context:
space:
mode:
authorDenis Kenzior <denis.kenzior@intel.com>2009-05-06 14:33:17 -0700
committerMarcel Holtmann <marcel.holtmann@intel.com>2009-05-06 14:42:54 -0700
commit64c42764736de15544e58666bdf97de088f7a7b5 (patch)
tree8f496fa6822a15acc593bd8ee66007ed0925efd3 /gatchat/ringbuffer.c
parent4ea27466bf3a5a3309d5ee689a1470c20c483ef9 (diff)
downloadofono-64c42764736de15544e58666bdf97de088f7a7b5.tar.bz2
Add AT chat library implementation
Diffstat (limited to 'gatchat/ringbuffer.c')
-rw-r--r--gatchat/ringbuffer.c199
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);
+}