Browse Source

add ringbuffer

xuqiang 11 tháng trước cách đây
mục cha
commit
751a5c9988
6 tập tin đã thay đổi với 516 bổ sung0 xóa
  1. 1 0
      .gitignore
  2. 50 0
      Makefile
  3. 58 0
      examples/example.c
  4. 153 0
      src/ringbuffer.c
  5. 138 0
      src/ringbuffer.h
  6. 116 0
      src/types.h

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+build/

+ 50 - 0
Makefile

@@ -0,0 +1,50 @@
+target = ringbuffer
+
+build_type ?= release
+build_type_dir ?= release
+build_dir = build/${build_type_dir}
+obj_dir := ${build_dir}/obj
+bin_dir := ${build_dir}/bin
+
+ifeq (${build_type}, release)
+	build_type_dir := release
+	DRFLAGS := -O3 -w
+else
+	build_type_dir = debug
+	DRFLAGS := -g3 -DDEBUG=1 -Wall -v
+endif
+
+gcc_std := -std=gnu99
+g++_std := -std=c++11
+includes = src
+
+CFLAGS := ${DRFLAGS} ${gcc_std} ${addprefix -I,${includes}}
+CXXFLAGS := ${DRFLAGS} ${g++_std} ${addprefix -I,${includes}}
+
+src_sources := $(shell find src -name '*.cpp' -or -name '*.c')
+example_sources :=  $(shell find examples -name '*.cpp' -or -name '*.c')
+sources := ${src_sources} ${example_sources}
+objects := $(sources:%=$(obj_dir)/%.o)
+
+# 默认目标:构建最终的可执行文件
+all: $(bin_dir)/$(target)
+
+# 链接目标:将所有.o文件链接成可执行文件
+$(bin_dir)/$(target): $(objects)
+	@mkdir -p $(dir $@)
+	${CC} $^ -o $@
+
+# c source
+$(obj_dir)/%.c.o: %.c
+	@mkdir -p $(dir $@)
+	${CC} ${CFLAGS} -c $< -o $@
+
+# c++ source
+$(obj_dir)/%.cpp.o: %.cpp
+	mkdir -p $(dir $@)
+	${CXX} ${CXXFLAGS} -c $< -o $@
+	
+.PHONY: clean
+
+clean:
+	rm -r ${build_dir}

+ 58 - 0
examples/example.c

@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <string.h>
+#include "ringbuffer.h"
+
+int main(int argc, char *argv[])
+{
+    ringbuffer_st ringbuffer;
+    ringbuffer_init(&ringbuffer, 1024);
+    memset(ringbuffer.data, 0 ,1024);
+
+    ringbuffer.head = 128;
+    ringbuffer.tail = 128;
+    ringbuffer.buffer_size = 0;
+
+    char buffer[128];
+
+    for(int i=0;i<128;i++)
+    {
+        buffer[i] = i;
+    }
+
+    ringbuffer_append(&ringbuffer, buffer, 128);
+    data_t data;
+    int ret = ringbuffer_data(ringbuffer, &data, 127);
+    if(ret == 0)
+        printf("read data: 0x%02x\n", data);
+    else
+        printf("out of range\n");
+
+    ret = ringbuffer_data(ringbuffer, &data, 128);
+    if(ret == 0)
+        printf("read data: 0x%02x\n", data);
+    else
+        printf("out of range\n");
+
+    ringbuffer_print(ringbuffer, true);
+
+    char temp[512];
+    int read_size = ringbuffer_read(ringbuffer, temp, 18);
+    printf("read size: %d\n", read_size);
+
+    for(int i=0;i<read_size;i++)
+    {
+        printf("0x%02x %d\n", temp[i], temp[i]);
+    }
+
+    ringbuffer_popup(&ringbuffer, read_size);
+    ringbuffer_print(ringbuffer, false);
+
+    ringbuffer_popup(&ringbuffer, 128);
+    ringbuffer_print(ringbuffer, false);
+
+    printf("ringbuffer empty: %s\n", ringbuffer_empty(ringbuffer) ? "true" : "false");
+
+    ringbuffer_release(&ringbuffer);
+
+    return 0;
+}

+ 153 - 0
src/ringbuffer.c

@@ -0,0 +1,153 @@
+/**
+ * @file    ringbuffer.c
+ * @brief   ringbuffer source file.
+ *
+ * @details 
+ *
+ * @author  jlgwch
+ * @date    2023-10-16
+ * @version 1.0
+ *
+ * @history
+ *  - 2023-10-16: jlgwch - Created the file.
+ *
+ * @copyright Copyright (c) 2023~ jlgwch. All rights reserved.
+ */
+
+#include "ringbuffer.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+bool ringbuffer_init(ringbuffer_st* ringbuffer, int size)
+{
+    ringbuffer->head = 0;
+    ringbuffer->tail = 0;
+    ringbuffer->buffer_size = 0;
+    ringbuffer->full_size = size;
+    ringbuffer->data = (data_t*)malloc(size);
+    if(ringbuffer->data == NULL)
+        return false;
+    return true;
+}
+
+void ringbuffer_release(ringbuffer_st* ringbuffer)
+{
+    if(ringbuffer->data)
+        free(ringbuffer->data);
+    ringbuffer->head = 0;
+    ringbuffer->tail = 0;
+    ringbuffer->buffer_size = 0;
+    ringbuffer->full_size = 0;
+}
+
+int ringbuffer_append(ringbuffer_st* ringbuffer, const data_t* buffer, int size)
+{
+    int len = ringbuffer->full_size - ringbuffer->buffer_size;
+
+    if(len >= size)
+    {
+        for(int i=0;i<size;i++)
+        {
+            ringbuffer->data[ringbuffer->tail] = buffer[i];
+            ringbuffer->tail = (ringbuffer->tail + 1) % ringbuffer->full_size;
+            ringbuffer->buffer_size++;
+        }
+        return 0;
+    }
+    return -1;
+}
+
+int ringbuffer_read(ringbuffer_st ringbuffer, data_t* data, int size)
+{
+    if(ringbuffer.buffer_size == 0)
+        return 0;
+
+    int len = ringbuffer.full_size - ringbuffer.head;
+
+    if(size > ringbuffer.buffer_size)
+    {
+        if(len >= ringbuffer.buffer_size)
+        {
+            memcpy(data, ringbuffer.data + ringbuffer.head, ringbuffer.buffer_size);
+        }
+        else
+        {
+            memcpy(data, &ringbuffer.data[ringbuffer.head], len);
+            memcpy(data + len, ringbuffer.data, ringbuffer.buffer_size - len);
+        }
+
+        return ringbuffer.buffer_size;
+    }
+
+    if(len >= size)
+    {
+        memcpy(data, ringbuffer.data + ringbuffer.head, size);
+    }
+    else
+    {
+        memcpy(data, &ringbuffer.data[ringbuffer.head], len);
+        memcpy(data + len, ringbuffer.data, size - len);
+    }
+    return size;
+}
+
+int ringbuffer_data(ringbuffer_st ringbuffer, data_t* data, int index)
+{
+    if(index >= ringbuffer.buffer_size || !data)
+        return -1;
+
+    *data = ringbuffer.data[(ringbuffer.head + index) % ringbuffer.full_size];
+    return 0;
+}
+
+void ringbuffer_popup(ringbuffer_st* ringbuffer, int size)
+{
+    if(ringbuffer->buffer_size >= size)
+    {
+        ringbuffer->head = (ringbuffer->head + size) % ringbuffer->full_size;
+        ringbuffer->buffer_size -= size;
+    }
+    else
+    {
+        ringbuffer->head = (ringbuffer->head + ringbuffer->buffer_size) % ringbuffer->full_size;
+        ringbuffer->buffer_size = 0;
+    }
+}
+
+void ringbuffer_clear(ringbuffer_st* ringbuffer)
+{
+    ringbuffer->head = 0;
+    ringbuffer->tail = 0;
+    ringbuffer->buffer_size = 0;
+}
+
+bool ringbuffer_empty(ringbuffer_st ringbuffer)
+{
+    if(ringbuffer.buffer_size == 0)
+        return true;
+    return false;
+}
+
+void ringbuffer_print(ringbuffer_st ringbuffer, bool print_buffer)
+{
+    printf("head index:  %d\n", ringbuffer.head);
+    printf("tail index:  %d\n", ringbuffer.tail);
+    printf("full size:   %d\n", ringbuffer.full_size);
+    printf("buffer size: %d\n", ringbuffer.buffer_size);
+ 
+    if(ringbuffer.buffer_size > 0 && print_buffer)
+    {
+        printf("bufer hex:   ");
+        for(int i = 0; i < ringbuffer.buffer_size; i++)
+        {
+           if(i != 0 && i % 20 == 0)
+           {
+               printf("\n");
+               printf("             ");
+           }
+           printf("0x%02x ", ringbuffer.data[(ringbuffer.head + i) % ringbuffer.full_size]);
+        }
+        printf("\n");
+    }
+}

+ 138 - 0
src/ringbuffer.h

@@ -0,0 +1,138 @@
+/**
+ * @file    ringbuffer.h
+ * @brief   ringbuffer header file.
+ *
+ * @details 
+ *
+ * @author  jlgwch
+ * @date    2023-10-16
+ * @version 1.0
+ *
+ * @history
+ *  - 2023-10-16: jlgwch - Created the file.
+ *
+ * @copyright Copyright (c) 2023~ jlgwch. All rights reserved.
+ */
+
+#ifndef __RINGBUFFER_H__
+#define __RINGBUFFER_H__
+
+#include "types.h"
+
+typedef uint8 data_t;
+
+typedef struct
+{
+    int head;
+    int tail;
+    int full_size;
+    int buffer_size;
+    data_t* data;
+} ringbuffer_st;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize a ring buffer.
+ *
+ * This function initializes a ring buffer with the given size.
+ *
+ * @param ringbuffer Pointer to the ring buffer structure to be initialized.
+ * @param size Size of the ring buffer.
+ * @return true if initialization is successful, false otherwise.
+ */
+bool ringbuffer_init(ringbuffer_st* ringbuffer, int size);
+
+/**
+ * @brief Release resources used by the ring buffer.
+ *
+ * This function releases any dynamically allocated memory associated with the ring buffer.
+ *
+ * @param ringbuffer Pointer to the ring buffer to be released.
+ */
+void ringbuffer_release(ringbuffer_st* ringbuffer);
+
+/**
+ * @brief Append data to the ring buffer.
+ *
+ * This function appends data to the ring buffer. If the buffer is full, do nothing.
+ *
+ * @param ringbuffer Pointer to the ring buffer.
+ * @param buffer Pointer to the data to be appended.
+ * @param size Size of the data to be appended.
+ * @return 0 if append is successful, -1 otherwise.
+ */
+int ringbuffer_append(ringbuffer_st* ringbuffer, const data_t* buffer, int size);
+
+/**
+ * @brief Read data from the ring buffer.
+ *
+ * This function reads data from the ring buffer. The function will attempt to read up to the given size.
+ *
+ * @param ringbuffer The ring buffer from which data is to be read.
+ * @param data Pointer to the buffer where read data will be stored.
+ * @param size Size of data to be read from the buffer.
+ * @return The number of bytes successfully read.
+ */
+int ringbuffer_read(ringbuffer_st ringbuffer, data_t* data, int size);
+
+/**
+ * @brief Get data from a specific index in the ring buffer.
+ *
+ * This function retrieves data from a specific index in the ring buffer without removing it.
+ *
+ * @param ringbuffer The ring buffer from which data is to be retrieved.
+ * @param index Index of the data to retrieve.
+ * @param data Pointer to the variable where the retrieved data will be stored.
+ * @return `0` if the data was successfully retrieved and stored in `data`; 
+ *         `-1` if the index is out of bounds or the data could not be retrieved.
+ */
+int ringbuffer_data(ringbuffer_st ringbuffer, data_t* data, int index);
+
+/**
+ * @brief Pop data from the front of the ring buffer.
+ *
+ * This function removes the specified number of elements from the front of the buffer.
+ *
+ * @param ringbuffer Pointer to the ring buffer.
+ * @param size Number of elements to remove from the front of the buffer.
+ */
+void ringbuffer_popup(ringbuffer_st* ringbuffer, int size);
+
+/**
+ * @brief Clear the ring buffer.
+ *
+ * This function clears all the data in the ring buffer, resetting it to an empty state.
+ *
+ * @param ringbuffer Pointer to the ring buffer.
+ */
+void ringbuffer_clear(ringbuffer_st* ringbuffer);
+
+/**
+ * @brief Check if the ring buffer is empty.
+ *
+ * This function checks if the ring buffer is empty, meaning no data is currently stored.
+ *
+ * @param ringbuffer The ring buffer to check for emptiness.
+ * @return true if the buffer is empty, false otherwise.
+ */
+bool ringbuffer_empty(ringbuffer_st ringbuffer);
+
+/**
+ * @brief Print the contents of the ring buffer.
+ *
+ * This function prints the info stored in the ring buffer.
+ *
+ * @param ringbuffer The ring buffer to print.
+ * @param print_buffer A boolean flag that controls whether the entire buffer contents should be printed.
+ *                     If `true`, the entire buffer will be printed; if `false`, only summary information will be printed.
+ */
+void ringbuffer_print(ringbuffer_st ringbuffer, bool print_buffer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __RINGBUFFER_H__

+ 116 - 0
src/types.h

@@ -0,0 +1,116 @@
+/**
+ * @file    types.h
+ * @brief   Basic data type redefinition.
+ *
+ * @details 
+ *
+ * @author  jlgwch
+ * @date    2025-04-22
+ * @version 1.0
+ *
+ * @history
+ *  - 2025-04-22: jlgwch - Created the file.
+ *
+ * @copyright Copyright (c) 2023~ jlgwch. All rights reserved.
+ */
+
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+/** define */
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+
+#ifndef INT16_MIN
+#define INT16_MIN (-32768)
+#endif
+
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483648)
+#endif
+
+#ifndef __cplusplus
+#ifndef bool
+typedef enum boolean { false, true } bool;
+#endif
+#endif
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+typedef signed char         int8;
+typedef signed short        int16;
+typedef signed int          int32;
+typedef signed long         int64;
+typedef unsigned char       uint8;
+typedef unsigned short      uint16;
+typedef unsigned int        uint32;
+typedef unsigned long       uint64;
+typedef float               float32;
+typedef double              float64;
+typedef struct complex_float32_st cpx_float32;
+typedef struct complex_int16_st cpx_int16;
+typedef struct complex_int32_st cpx_int32;
+
+// For MCU
+typedef int8                S8;
+typedef int16               S16;
+typedef int32               S32;
+typedef int64               S64;
+
+typedef uint8               U8;
+typedef uint16              U16;
+typedef uint32              U32;
+typedef uint64              U64;
+
+typedef float32             F32;
+typedef float64             F64;
+
+typedef cpx_float32         CPX_F32;
+typedef cpx_int32           CPX_I32;
+typedef cpx_int16           CPX_I16;
+
+/** struct */
+struct complex_float32_st
+{
+    float32 r;
+    float32 i;
+};
+
+struct complex_int32_st
+{
+    int32 r;
+    int32 i;
+};
+
+struct complex_int16_st
+{
+    int16 r;
+    int16 i;
+};
+
+#define TYPES_DESCRIPTION() \
+{ \
+    printf("+--------------+--------+---------+---------------------------------------------------+\n"); \
+    printf("| Data Types   |   Bits |   Bytes | Value Range                                       |\n"); \
+    printf("|--------------+--------+---------+---------------------------------------------------|\n"); \
+    printf("| int8/S8      |      8 |       1 | -128 ~ +127                                       |\n"); \
+    printf("| uint8/U8     |      8 |       1 | 0 ~ 255                                           |\n"); \
+    printf("| int16/S16    |     16 |       2 | -32768 ~ +32767                                   |\n"); \
+    printf("| uint16/U16   |     16 |       2 | 0 ~ 65535                                         |\n"); \
+    printf("| int32/S32    |     32 |       4 | -2147483648 ~ +2147483647                         |\n"); \
+    printf("| uint32/U32   |     32 |       4 | 0 ~ 4294967295                                    |\n"); \
+    printf("| int64/S64    |     32 |       8 | -9223372036854775808 ~ +9223372036854775807       |\n"); \
+    printf("| uint64/U64   |     32 |       8 | 0 ~ 18446744073709551615                          |\n"); \
+    printf("| float32/F32  |     32 |       4 | 1.175494351E-38 ~ 3.402823466E+38                 |\n"); \
+    printf("| float64/F64  |     64 |       8 | 2.2250738585072014E-308 ~ 1.7976931348623158E+308 |\n"); \
+    printf("+--------------+--------+---------+---------------------------------------------------+\n"); \
+}
+
+#endif