Browse Source

Ещё одна реализация кольцевого буфера на C.

Vladimir N. Shilov 8 years ago
parent
commit
462bf4f913
1 changed files with 199 additions and 0 deletions
  1. 199 0
      Ring buffer in C.txt

+ 199 - 0
Ring buffer in C.txt

@@ -0,0 +1,199 @@
+http://tath.eu/code/ring-buffer-in-c/
+
+Ring buffer is very common and useful data structure, excellent for storing 
+asynchronous data from multiple sources in embedded devices.
+
+ringbuffer.h
+// Simple prove-of-concept ring buffer
+// Author: Adam Orcholski, www.tath.eu
+#pragma once
+ 
+// types
+typedef struct ring_buffer_s
+{
+    unsigned char * data;   // pointer to external buffer
+    int size;               // size of external buffer
+    int head;               // index of free space in external buffer
+    int tail;               // index of last item to be read
+    int count;              // hold number of items stored but not read
+} ring_buffer_t;
+ 
+// interface
+void RING_Init(ring_buffer_t * const buff_state, unsigned char * in_buffer, int buffer_size_in_bytes);
+void RING_Reset(ring_buffer_t * const buff_state);      // note: does not clear external buffer
+int  RING_IsEmpty(ring_buffer_t * const buff_state);    // return non-zero if buffer is empty
+int  RING_IsFull(ring_buffer_t * const buff_state);     // return non-zero if buffer is full
+int  RING_AddItem(ring_buffer_t * const buff_state, unsigned char new_item);            // return non-zero if buffer is full
+int  RING_GetItem(ring_buffer_t * const buff_state, unsigned char * const out_item);    // return non-zero if buffer is empty
+
+ringbuffer.c
+// Simple prove-of-concept ring buffer
+// Author: Adam Orcholski, www.tath.eu
+ 
+#include <ringbuffer.h>
+#include <assert.h>
+ 
+ 
+// function definitions
+void RING_Init(ring_buffer_t * const buff_state, unsigned char * in_buffer, int buffer_size_in_bytes)
+{
+    assert(0 != buff_state);
+    assert(0 != in_buffer);
+    assert(buffer_size_in_bytes > 0);
+ 
+    buff_state->data = in_buffer;
+    buff_state->size = buffer_size_in_bytes;
+    buff_state->head = 0;
+    buff_state->tail = 0;
+    buff_state->count = 0;
+}
+ 
+void RING_Reset(ring_buffer_t * const buff_state)
+{
+    assert(0 != buff_state);
+ 
+    buff_state->head = 0;
+    buff_state->tail = 0;
+    buff_state->count = 0;
+}
+ 
+// return non-zero value if buffer is empty
+int  RING_IsEmpty(ring_buffer_t * const buff_state)
+{
+    int fBufferIsEmpty = 0;
+ 
+    assert(0 != buff_state);
+ 
+    if (0 == buff_state->count)
+    {
+        fBufferIsEmpty = 1;
+    }
+ 
+    return fBufferIsEmpty;
+}
+ 
+// return non-zero value if buffer is full
+int  RING_IsFull(ring_buffer_t * const buff_state)
+{
+    int fBufferIsFull = 0;
+ 
+    assert(0 != buff_state);
+ 
+    if (buff_state->count >= buff_state->size)
+    {
+        fBufferIsFull = 1;
+    }
+ 
+    return fBufferIsFull;
+}
+ 
+// return non-zero value if buffer is full
+int  RING_AddItem(ring_buffer_t * const buff_state, unsigned char new_item)
+{
+    int fBufferIsFull = 0;
+ 
+    assert(0 != buff_state);
+ 
+    fBufferIsFull = RING_IsFull(buff_state);
+ 
+    if (!fBufferIsFull)
+    {
+        buff_state->data[buff_state->head] = new_item;
+        buff_state->head++;
+        buff_state->count++;
+ 
+        if (buff_state->head >= buff_state->size)
+        {
+            buff_state->head = 0;
+        }
+    }
+ 
+ 
+    return fBufferIsFull;
+}
+ 
+// return non-zero value if buffer is empty
+int  RING_GetItem(ring_buffer_t * const buff_state, unsigned char * const out_item)
+{
+    int fBufferIsEmpty = 0;
+ 
+    assert(0 != buff_state);
+    assert(0 != out_item);
+ 
+    fBufferIsEmpty = RING_IsEmpty(buff_state);
+ 
+    if (!fBufferIsEmpty)
+    {
+        *out_item = buff_state->data[buff_state->tail];
+        buff_state->tail++;
+        buff_state->count--;
+ 
+        if (buff_state->tail >= buff_state->size)
+        {
+            buff_state->tail = 0;
+        }
+    }
+ 
+    return fBufferIsEmpty;
+}
+
+and example/test compiled in Microsoft Visual Studio:
+
+main.c
+// Simple prove-of-concept ring buffer example
+// Author: Adam Orcholski, www.tath.eu
+ 
+#include <stdio.h>
+#include <ringbuffer.h>
+ 
+#define BUFF_SIZE 4
+unsigned char bufffeeer[BUFF_SIZE];
+ 
+ring_buffer_t buff;
+ 
+int main()
+{
+    RING_Init(&buff, bufffeeer, sizeof(bufffeeer));
+ 
+    char c = 0;
+ 
+    while (c != 'q')
+    {
+        static char write_char = 'a';
+        c = getchar();
+         
+        int ret = 0;
+ 
+        if (c == 'w')
+        {
+            ret = RING_AddItem(&buff, write_char);
+            if (ret)
+            {
+                printf("buffer full\r\n");
+            }
+            else
+            {
+                printf("written char = %c\r\n", write_char);
+            }
+            write_char++;
+            if (write_char == 'z') { write_char = 'a'; }
+        }
+        else if (c == 's')
+        {
+            char out;
+            ret = RING_GetItem(&buff, &out);
+            if (ret)
+            {
+                printf("buffer empty\r\n");
+            }
+            else
+            {
+                printf("read char = %c\r\n", out);
+            }
+        }
+    }
+ 
+    return 0;
+}
+
+Run example, and press W key to add item to buffer and S key to read last item. Press Q to quit.