为类似面向对象,因为不能隐性传参,对象的方法必须把对象本身传入。
上代码
ring_buffer.c
/* File Info
* Author: Holy.Han
* CreateTime: 2020/7/18 下午11:39:51
* LastEditor: Holy.Han
* ModifyTime: 2020/7/18 下午11:39:54
* Description:
*/
#include "ring_buffer.h"
#include <stdio.h>
typedef struct
{
uint8_t *buffer; //存放实际的数据
uint32_t read_offset; //读取地址相对buffer的偏移量
uint32_t write_offset; //写入地址相对buffer的偏移量
uint32_t valid_size; //buffer的有效size
uint32_t total_size; //buffer的总大小,即init时malloc的size
} ring_buf_t;
typedef struct
{
ring_buf_t ring_buf;
ring_t ring;
} ring_obj_t;
static void ring_destroy(ring_t *ring);
static void ring_write(ring_t *ring, void *write, uint32_t size);
static void ring_read(ring_t *ring, void *read, uint32_t size);
static uint32_t ring_valid(ring_t *ring);
static void ring_print(const char *str, uint8_t *data, uint32_t len)
{
printf("%s:\r\n\t{ ", str);
for (uint32_t i = 0; i < len; i++)
{
if (i == (len - 1))
{
printf("0x%02X", *(data + i));
}
else
{
printf("0x%02X, ", *(data + i));
}
if (i % 16 == 15 && i != (len - 1))
{
printf("\r\n\t ");
}
}
printf(" }\r\n");
}
ring_t *new_ring(uint32_t size)
{
ring_obj_t *ring_obj = NULL;
ring_obj = ring_alloc(sizeof(ring_obj_t));
if (ring_obj == NULL)
{
return NULL;
}
#if DBG_ENBALE
printf("new ring addr=0x%p\r\n", ring_obj);
#endif
ring_obj->ring_buf.buffer = ring_alloc(size);
if (ring_obj->ring_buf.buffer == NULL)
{
ring_free(ring_obj);
return NULL;
}
#if DBG_ENBALE
printf("ring 0x%p buffer addr=0x%p, size=%d\r\n", ring_obj, ring_obj->ring_buf.buffer, size);
#endif
ring_obj->ring_buf.total_size = size;
ring_obj->ring.destroy = ring_destroy;
ring_obj->ring.write = ring_write;
ring_obj->ring.read = ring_read;
ring_obj->ring.valid = ring_valid;
#if DBG_ENBALE
printf("ring 0x%p func addr=0x%p\r\n", ring_obj, ring_obj->ring);
#endif
return &ring_obj->ring;
}
static void ring_destroy(ring_t *ring)
{
if (ring == NULL)
{
return;
}
ring_obj_t *ring_obj = (ring_obj_t *)(((ring_buf_t *)ring) - 1);
if (ring_obj->ring_buf.buffer != NULL)
{
ring_free(ring_obj->ring_buf.buffer);
}
ring_free(ring_obj);
#if DBG_ENBALE
printf("destroy ring=0x%p\r\n", ring_obj);
#endif
}
static void ring_write(ring_t *ring, void *write, uint32_t size)
{
if (ring == NULL || write == NULL)
{
return;
}
#if DBG_ENBALE
ring_print("ring write", (uint8_t *)write, size);
#endif
ring_buf_t *ring_buffer = (ring_buf_t *)(((ring_buf_t *)ring) - 1);
uint32_t write_offset = ring_buffer->write_offset;
uint32_t total_size = ring_buffer->total_size;
uint32_t first_write_size = 0;
if (ring_buffer->valid_size + size > total_size) //ring_buffer->buffer未使用的总大小比需要写入的size小
{
// todo printf
return;
}
if (size + write_offset <= total_size) //ring_buffer->buffer的后段未写入的空间不小于size
{
memcpy(ring_buffer->buffer + write_offset, write, size);
}
else //ring_buffer->buffer的后段未写入的空间小于size,这时候需要先在后面写入一部分,然后返回头部,从前面接着写入
{
first_write_size = total_size - write_offset;
memcpy(ring_buffer->buffer + write_offset, write, first_write_size);
memcpy(ring_buffer->buffer, (const uint8_t *)write + first_write_size, size - first_write_size);
}
ring_buffer->write_offset += size;
ring_buffer->write_offset %= total_size;
ring_buffer->valid_size += size;
#if DBG_ENBALE
ring_print("ring now", (uint8_t *)(ring_buffer->buffer), ring_buffer->valid_size);
#endif
}
static void ring_read(ring_t *ring, void *read, uint32_t size)
{
if (ring == NULL || read == NULL || size == 0)
{
return;
}
ring_buf_t *ring_buffer = (ring_buf_t *)(((ring_buf_t *)ring) - 1);
uint32_t read_offset = ring_buffer->read_offset;
uint32_t total_size = ring_buffer->total_size;
uint32_t first_read_size = 0;
if (size > ring_buffer->valid_size)
{
//todo print
return;
}
if (total_size - read_offset >= size)
{
memcpy(read, ring_buffer->buffer + read_offset, size);
}
else
{
first_read_size = total_size - read_offset;
memcpy(read, ring_buffer->buffer + read_offset, first_read_size);
memcpy((uint8_t *)read + first_read_size, ring_buffer->buffer, size - first_read_size);
}
#if DBG_ENBALE
ring_print("ring read", (uint8_t *)read, size);
#endif
ring_buffer->read_offset += size;
ring_buffer->read_offset %= total_size;
ring_buffer->valid_size -= size;
#if DBG_ENBALE
ring_print("ring now", (uint8_t *)(ring_buffer->buffer), ring_buffer->valid_size);
#endif
}
static uint32_t ring_valid(ring_t *ring)
{
if (ring == NULL)
{
return 0;
}
ring_buf_t *ring_buffer = (ring_buf_t *)(((ring_buf_t *)ring) - 1);
return ring_buffer->valid_size;
}
最重要的头文件
ring_buffer.h
/* File Info
* Author: Holy.Han
* CreateTime: 2020/7/18 下午11:40:15
* LastEditor: Holy.Han
* ModifyTime: 2020/7/18 下午11:40:18
* Description:
*/
#ifndef _RING_BUFFER_H
#define _RING_BUFFER_H
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
/* */
#define ring_alloc(size) calloc(1, size)
#define ring_free(p) free(p)
#define DBG_ENBALE 1
struct ring
{
void (*destroy)(struct ring *);
void (*write)(struct ring *, void *, uint32_t);
void (*read)(struct ring *, void *, uint32_t);
uint32_t (*valid)(struct ring *);
};
typedef struct ring ring_t;
ring_t *new_ring(uint32_t size);
#endif /* _RING_BUFFER_H */
demo.c
#include <stdio.h>
#include "utils\ring_buffer.h"
int main(int argc, char **argv)
{
uint8_t write[40];
uint8_t read[100];
for (size_t i = 0; i < 16; i++)
{
write[i] = i + '0';
}
ring_t *myring = new_ring(128);
myring->write(myring, write, 16);
for (size_t i = 0; i < 32; i++)
{
write[i] = i + 'a';
}
myring->write(myring, write, 32);
uint32_t size = myring->valid(myring);
myring->read(myring, read, size);
myring->destroy(myring);
return 0;
}