封装 ring_buffer,在程序中方便使用缓存

1、ring_buffer.c

#include "ring_buffer.h"
#include <string.h>

static void ring_buf_internal_reset(struct ring_buf *buf, int32_t value)
{
	buf->put_head = buf->put_tail = buf->put_base = value;
	buf->get_head = buf->get_tail = buf->get_base = value;
}

static uint32_t ring_buf_size_get(struct ring_buf *buf)
{
	return buf->put_tail - buf->get_head;
}

uint32_t ring_buf_space_get(struct ring_buf *buf)
{
	return buf->size - (buf->put_head - buf->get_tail);
}

uint32_t ring_buf_put_claim(struct ring_buf *buf, uint8_t **data, uint32_t size)
{
	uint32_t free_space, wrap_size;
	int32_t base;

	base = buf->put_base;
	wrap_size = buf->put_head - base;
	if (unlikely(wrap_size >= buf->size)) {
		/* put_base is not yet adjusted */
		wrap_size -= buf->size;
		base += buf->size;
	}
	wrap_size = buf->size - wrap_size;

	free_space = ring_buf_space_get(buf);
	size = MIN(size, free_space);
	size = MIN(size, wrap_size);

	*data = &buf->buffer[buf->put_head - base];
	buf->put_head += size;

	return size;
}

int ring_buf_put_finish(struct ring_buf *buf, uint32_t size)
{
	uint32_t finish_space, wrap_size;

	finish_space = buf->put_head - buf->put_tail;
	if (unlikely(size > finish_space)) {
		return -1;
	}

	buf->put_tail += size;
	buf->put_head = buf->put_tail;

	wrap_size = buf->put_tail - buf->put_base;
	if (unlikely(wrap_size >= buf->size)) {
		/* we wrapped: adjust put_base */
		buf->put_base += buf->size;
	}

	return 0;
}

uint32_t ring_buf_get_claim(struct ring_buf *buf, uint8_t **data, uint32_t size)
{
	uint32_t available_size, wrap_size;
	int32_t base;

	base = buf->get_base;
	wrap_size = buf->get_head - base;
	if (unlikely(wrap_size >= buf->size)) {
		/* get_base is not yet adjusted */
		wrap_size -= buf->size;
		base += buf->size;
	}
	wrap_size = buf->size - wrap_size;

	available_size = ring_buf_size_get(buf);
	size = MIN(size, available_size);
	size = MIN(size, wrap_size);

	*data = &buf->buffer[buf->get_head - base];
	buf->get_head += size;

	return size;
}

int ring_buf_get_finish(struct ring_buf *buf, uint32_t size)
{
	uint32_t finish_space, wrap_size;

	finish_space = buf->get_head - buf->get_tail;
	if (unlikely(size > finish_space)) {
		return -1;
	}

	buf->get_tail += size;
	buf->get_head = buf->get_tail;

	wrap_size = buf->get_tail - buf->get_base;
	if (unlikely(wrap_size >= buf->size)) {
		/* we wrapped: adjust get_base */
		buf->get_base += buf->size;
	}

	return 0;
}

uint32_t ring_buf_put(struct ring_buf *buf, const uint8_t *data, uint32_t size)
{
	uint8_t *dst;
	uint32_t partial_size;
	uint32_t total_size = 0U;
	// int err;

	do {
		partial_size = ring_buf_put_claim(buf, &dst, size);
		memcpy(dst, data, partial_size);
		total_size += partial_size;
		size -= partial_size;
		data += partial_size;
	} while (size && partial_size);

	ring_buf_put_finish(buf, total_size);

	return total_size;
}

uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size)
{
	uint8_t *src;
	uint32_t partial_size;
	uint32_t total_size = 0U;
	__unused int err;

	do {
		partial_size = ring_buf_get_claim(buf, &src, size);
		if (data) {
			memcpy(data, src, partial_size);
			data += partial_size;
		}
		total_size += partial_size;
		size -= partial_size;
	} while (size && partial_size);

	err = ring_buf_get_finish(buf, total_size);


	return total_size;
}

int ring_buf_init(struct ring_buf *buf,
				 uint32_t size,
				 uint8_t *data)
{
	if(size<=RING_BUFFER_MAX_SIZE && buf!=NULL && data!=NULL){
		buf->size = size;
		buf->buffer = data;
		ring_buf_internal_reset(buf, 0);
		return 0;
	}
	return -1;
}



2、ring_buffer.h

#ifndef __RING_BUFFER_H_
#define __RING_BUFFER_H_

#include <stdint.h>
#define MIN(a,b) (((a) < (b)) ? (a) : (b))

#define RING_BUFFER_MAX_SIZE 0xffff
#define likely(x)   __builtin_expect((long)!!(x), 1L)
#define unlikely(x) __builtin_expect((long)!!(x), 0L)


struct ring_buf {
	uint8_t *buffer;
	int32_t put_head;
	int32_t put_tail;
	int32_t put_base;
	int32_t get_head;
	int32_t get_tail;
	int32_t get_base;
	uint32_t size;
};


uint32_t ring_buf_space_get(struct ring_buf *buf);
uint32_t ring_buf_put_claim(struct ring_buf *buf, uint8_t **data, uint32_t size);
int ring_buf_put_finish(struct ring_buf *buf, uint32_t size);
uint32_t ring_buf_get_claim(struct ring_buf *buf, uint8_t **data, uint32_t size)int ring_buf_get_finish(struct ring_buf *buf, uint32_t size);

uint32_t ring_buf_put(struct ring_buf *buf, const uint8_t *data, uint32_t size);
uint32_t ring_buf_get(struct ring_buf *buf, uint8_t *data, uint32_t size);
int ring_buf_init(struct ring_buf *buf, uint32_t size, uint8_t *data);

#endif

3、简单使用 ring_buffer 存取

static uint8_t my_buf[100];
static struct ring_buf my_rb;
// 初始化 ring_buffer,这里使用了数组作为缓存,当然也可以使用 malloc申请的空间作为缓存
ring_buf_init(&my_rb, sizeof(my_buf), my_buf);

// 把数据放到缓存里
uint8_t data[5] = {0x01, 0x10, 0x02, 0x20, 0x66};
ring_buf_put(&my_rb, data, sizeof(data));

uint8_t data_buf[20];
uint32_t len = ring_buf_get(my_rb, data_buf, sizeof(data_buf));

4、其他 API
(1)ring_buf_space_get 用于获取ring_buffer 中未使用的缓存空间(字节)
(2)ring_buf_put_claim 和 ring_buf_put_finish 是一对的,用于存入数据到缓存中,功能与 ring_buf_put 相似,但这对函数更加高效,因为它没有拷贝;需要注意的是需要先使用 ring_buf_put_claim 再调用 ring_buf_put_finish
(3)ring_buf_get_claim 和 ring_buf_get_finish 是一对的,用于取出并使用缓存中的数据,功能与 ring_buf_get 相似,但这对函数更加高效,因为它没有拷贝;需要注意的是需要先使用 ring_buf_get_claim 再调用 ring_buf_get_finish

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yyyang88

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值