commit 0fb32781c9631d62b312af6427a100a32a4081ed
Author: Ondřej Hruška <ondra@ondrovo.com>
Date:   Sun Nov 29 12:36:14 2015 +0100

    source added

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d91e016
--- /dev/null
+++ b/README.md
@@ -0,0 +1,33 @@
+Circular byte buffer
+====================
+
+This is a circular buffer implementation, useful for embedded systems (buffer for UART RX queue etc).
+
+
+Usage
+-----
+
+```c
+#include <stdint.h>
+
+uint8_t buffer[32]; // array backing the buffer
+
+CircularByteBuffer cb; // buffer instance
+
+void main()
+{
+	cbuf_init(&cb, buffer, 32); // init the buffer
+	
+	// now it's ready for use!
+}
+```
+
+Many function return success flag, so make sure to check the return values.
+
+False is returned on buffer overflow / underflow, attempted read past available data size etc. See the header file for details.
+
+
+License
+-------
+
+Do whatever you want with the code.
\ No newline at end of file
diff --git a/circbuf.c b/circbuf.c
new file mode 100644
index 0000000..b9d2892
--- /dev/null
+++ b/circbuf.c
@@ -0,0 +1,175 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "circbuf.h"
+
+
+void cbuf_init(CircularBuffer *inst, uint8_t *buffer, uint16_t length)
+{
+	inst->buffer = buffer;
+	inst->capacity = length;
+
+	cbuf_clear(inst);
+}
+
+
+bool cbuf_full(CircularBuffer *inst)
+{
+	return inst->data_len == inst->capacity;
+}
+
+
+bool cbuf_empty(CircularBuffer *inst)
+{
+	return inst->data_len == 0;
+}
+
+
+bool cbuf_write(CircularBuffer *inst, uint8_t b)
+{
+	if (cbuf_full(inst)) return false;
+
+	inst->buffer[inst->write_pos] = b;
+
+	inst->write_pos++;
+	inst->data_len++;
+
+	// wrap
+	if (inst->write_pos >= inst->capacity) {
+		inst->write_pos = 0;
+	}
+
+	return true;
+}
+
+
+bool cbuf_read(CircularBuffer *inst, uint8_t *b)
+{
+	if (cbuf_empty(inst)) return false;
+
+	*b = inst->buffer[inst->read_pos];
+
+	inst->read_pos++;
+	inst->data_len--;
+
+	// wrap
+	if (inst->read_pos >= inst->capacity) {
+		inst->read_pos = 0;
+	}
+
+	return true;
+}
+
+
+bool cbuf_peek(CircularBuffer *inst, uint8_t *b)
+{
+	if (cbuf_empty(inst)) return false;
+
+	*b = inst->buffer[inst->read_pos];
+	return true;
+}
+
+
+uint16_t cbuf_data_size(CircularBuffer *inst)
+{
+	return inst->data_len;
+}
+
+
+uint16_t cbuf_free_space(CircularBuffer *inst)
+{
+	return inst->capacity - inst->data_len;
+}
+
+
+void cbuf_clear(CircularBuffer *inst)
+{
+	inst->read_pos = 0;
+	inst->write_pos = 0;
+	inst->data_len = 0;
+}
+
+
+bool cbuf_write_n(CircularBuffer *inst, const uint8_t *b, uint16_t count)
+{
+	if (cbuf_free_space(inst) < count) return false;
+
+	for (uint16_t i = 0; i < count; i++) {
+		cbuf_write(inst, *(b + i));
+	}
+
+	return true;
+}
+
+
+bool cbuf_write_string(CircularBuffer *inst, const char *str)
+{
+	return cbuf_write_n(inst, (uint8_t *) str, strlen(str));
+}
+
+
+bool cbuf_read_n(CircularBuffer *inst, uint8_t *buf, uint16_t len)
+{
+	if (cbuf_data_size(inst) < len) return false;
+
+	for (uint16_t i = 0; i < len; i++) {
+		cbuf_read(inst, buf + i);
+	}
+
+	return true;
+}
+
+
+bool cbuf_read_string(CircularBuffer *inst, char *str, uint16_t len)
+{
+	bool b = cbuf_read_n(inst, (uint8_t *) str, len);
+	if (!b) return false;
+
+	str[len] = 0;
+
+	return true;
+}
+
+
+uint16_t cbuf_read_upto(CircularBuffer *inst, uint8_t *buf, uint16_t max)
+{
+	uint16_t i;
+	for (i = 0; i < max; i++) {
+		if (cbuf_empty(inst)) break;
+		cbuf_read(inst, buf + i);
+	}
+
+	return i;
+}
+
+
+uint16_t cbuf_read_string_upto(CircularBuffer *inst, char *str, uint16_t max)
+{
+	uint16_t cnt = cbuf_read_upto(inst, (uint8_t *) str, max);
+	str[cnt] = 0;
+	return cnt;
+}
+
+
+int32_t cbuf_find(CircularBuffer *inst, uint8_t b)
+{
+	uint16_t cursor = inst->read_pos;
+	uint16_t cnt = 0;
+
+	while (cursor != inst->write_pos) {
+
+		if (inst->buffer[cursor] == b) return cnt;
+
+		cursor++;
+		cnt++;
+
+		// wrap
+		if (cursor >= inst->capacity) {
+			cursor = 0;
+		}
+	}
+
+	return -1;
+}
+
diff --git a/circbuf.h b/circbuf.h
new file mode 100644
index 0000000..6fb0d97
--- /dev/null
+++ b/circbuf.h
@@ -0,0 +1,79 @@
+#pragma once
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct {
+	uint8_t *buffer;
+	uint16_t capacity;
+	uint16_t read_pos;
+	uint16_t write_pos;
+	uint16_t data_len;
+} CircularByteBuffer;
+
+
+/** Init a buffer */
+void cbuf_init(CircularByteBuffer *inst, uint8_t *buffer, uint16_t length);
+
+
+/** Test for full buffer */
+bool cbuf_full(CircularByteBuffer *inst);
+
+
+/** Test for empty buffer */
+bool cbuf_empty(CircularByteBuffer *inst);
+
+
+/** Write a byte to buffer, returns success */
+bool cbuf_write(CircularByteBuffer *inst, uint8_t b);
+
+
+/** Read a byte from the buffer, return susccess */
+bool cbuf_read(CircularByteBuffer *inst, uint8_t *b);
+
+
+/** Get byte at the read cursor, without incrementing it. False on empty. */
+bool cbuf_peek(CircularByteBuffer *inst, uint8_t *b);
+
+
+/** Get data count */
+uint16_t cbuf_data_size(CircularByteBuffer *inst);
+
+
+/** Get free space in the buffer */
+uint16_t cbuf_free_space(CircularByteBuffer *inst);
+
+
+/** Remove all data from buffer */
+void cbuf_clear(CircularByteBuffer *inst);
+
+
+/** Write N bytes. Returns success */
+bool cbuf_write_n(CircularByteBuffer *inst, const uint8_t *b, uint16_t count);
+
+
+/** Write a string (without \0) */
+bool cbuf_write_string(CircularByteBuffer *inst, const char *str);
+
+
+/** Read N bytes, if available. Returns success. */
+bool cbuf_read_n(CircularByteBuffer *inst, uint8_t *buf, uint16_t len);
+
+
+/** Read string of given length, append \0. `str` must be len+1 long */
+bool cbuf_read_string(CircularByteBuffer *inst, char *str, uint16_t len);
+
+
+/** Read up to N bytes. Returns byte count */
+uint16_t cbuf_read_upto(CircularByteBuffer *inst, uint8_t *buf, uint16_t max);
+
+
+/** Read string up to N chars long, append \0. `str` must be max+1 long */
+uint16_t cbuf_read_string_upto(CircularByteBuffer *inst, char *str, uint16_t max);
+
+
+/**
+ * Search buffer and return position of the first occurence
+ * of the given byte (position relative to read_pos).
+ * Returns -1 if not found.
+ */
+int32_t cbuf_find(CircularByteBuffer *inst, uint8_t b);