mylibrary/c/cirbuff/cirbuff.c

330 lines
7 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* cirbuff.c - 环形缓冲区的实现
*
* 采用记录读写位置的方法实现,没有做线程安全处理。
*/
#include <stdlib.h>
#include "cirbuff.h"
struct cirbuff
{
uint8_t *buff;
uint32_t rpos;
uint32_t wpos;
uint32_t size;
uint32_t cnt;
uint32_t update;
};
// 静态函数声明
static uint32_t cirbuff_cover_write(cirbuff_handle cbuff_h,
uint8_t *indata, uint32_t inlen);
static uint32_t cirbuff_nocover_write(cirbuff_handle cbuff_h,
uint8_t *indata, uint32_t inlen);
static uint32_t cirbuff_clear_read(cirbuff_handle cbuff_h,
uint8_t *outdata, uint32_t outlen);
static uint32_t cirbuff_noclear_read(cirbuff_handle cbuff_h,
uint8_t *outdata, uint32_t outlen);
// 以下函数为对循环缓冲区的操作
/*
* cirbuff_creat - 创建一个环形缓冲区
*
* 所做的包括分配空间和初始变量赋值
*/
cirbuff_handle cirbuff_creat(uint32_t size)
{
struct cirbuff *cbuff = NULL;
int32_t rlt = 0;
if (size == 0)
rlt = -1;
else
rlt = 1;
// 为cbuff分配空间
if (rlt)
{
cbuff = (struct cirbuff *)malloc(sizeof(*cbuff));
if (cbuff == NULL)
rlt = -2;
}
// 为cbuff->buff分配空间
if (rlt)
{
cbuff->buff = (uint8_t *)malloc(size);
if (cbuff->buff == NULL)
{
free(cbuff);
cbuff = NULL;
rlt = -2;
}
}
if (rlt)
{
cbuff->rpos = 0;
cbuff->wpos = 0;
cbuff->size = size;
cbuff->cnt = 0;
cbuff->update = 0;
}
return (cirbuff_handle)cbuff;
}
/*
* cirbuff_write - 往环形缓冲区中写入数据
* @cbuff:
* @indata:
* @inlen:
* @be_cover: 0表示非覆盖1表示覆盖
*
* 覆盖写入时如果buff满会循环覆盖先前已有的数据并返回覆盖的数据计数。
* 非覆盖写入时如果写入下一个数据时buff已满就退出并返回写入的数据计数。
*/
uint32_t cirbuff_write(cirbuff_handle cbuff_h,
uint8_t *indata, uint32_t inlen, uint8_t be_cover)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
int32_t ret;
if (be_cover)
ret = cirbuff_cover_write(cbuff, indata, inlen);
else
ret = cirbuff_nocover_write(cbuff, indata, inlen);
return ret;
}
/*
* cirbuff_cover_write - 覆盖写入循环缓冲区
*
* 返回覆盖的字节数
*/
static uint32_t cirbuff_cover_write(cirbuff_handle cbuff_h,
uint8_t *indata, uint32_t inlen)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
uint32_t i;
uint32_t cover_cnt = 0;
for (i = 0; i < inlen; i++)
{
cbuff->buff[cbuff->wpos] = indata[i];
// 更新状态
cbuff->wpos++;
if (cbuff->wpos == cbuff->size)
cbuff->wpos = 0;
// 是否存储区满
if (cirbuff_be_full(cbuff))
{
cbuff->rpos = cbuff->wpos;
cover_cnt++;
}
else
{
cbuff->cnt++;
}
}
if (i)
cbuff->update = 1;
return cover_cnt;
}
/*
* cirbuff_nocover_write - 非覆盖写入循环缓冲区
*
* 返回写入的字节数
*/
static uint32_t cirbuff_nocover_write(cirbuff_handle cbuff_h,
uint8_t *indata, uint32_t inlen)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
uint32_t i = 0;
while (i < inlen)
{
// 是否存储区满
if (cirbuff_be_full(cbuff))
break;
// 更新状态
cbuff->buff[cbuff->wpos++] = indata[i];
cbuff->cnt++;
if (cbuff->wpos == cbuff->size)
cbuff->wpos = 0;
i++;
}
if (i)
cbuff->update = 1;
return i;
}
/*
* cirbuff_clear_read - 读循环缓冲区的数据,并且清除已读的数据
*
* 参数outdata可以为NULL此时读操作的赋值语句被屏蔽可用于删除一段数据
* 返回已读的字节数和outdata是否为NULL无关
*/
static uint32_t cirbuff_clear_read(cirbuff_handle cbuff_h,
uint8_t *outdata, uint32_t outlen)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
uint32_t i = 0;
while (i < outlen)
{
// 是否存储区空
if (cirbuff_be_empty(cbuff))
break;
if (outdata != NULL)
outdata[i] = cbuff->buff[cbuff->rpos];
// 更新状态
cbuff->cnt--;
cbuff->rpos++;
if (cbuff->rpos == cbuff->size)
cbuff->rpos = 0;
i++;
}
if (i)
cbuff->update = 0;
return i;
}
/*
* cirbuff_noclear_read - 读循环缓冲区的数据,不会清除已读的数据
*
* 参数outdata可以为NULL此时读操作的赋值语句被屏蔽可用于仅仅置更新状态的操作
* 返回已读的字节数和outdata是否为NULL无关
*/
static uint32_t cirbuff_noclear_read(cirbuff_handle cbuff_h,
uint8_t *outdata, uint32_t outlen)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
uint32_t i = 0;
uint32_t cnt = cbuff->cnt;
uint32_t rpos = cbuff->rpos;
while (i < outlen)
{
// 是否存储区空
if (cirbuff_be_empty(cbuff))
break;
if (outdata != NULL)
outdata[i] = cbuff->buff[rpos];
// 更新状态
cnt--;
rpos++;
if (rpos == cbuff->size)
rpos = 0;
i++;
}
if (i)
cbuff->update = 0;
return i;
}
uint32_t cirbuff_read(cirbuff_handle cbuff_h,
uint8_t *outdata, uint32_t outlen, uint8_t be_clear)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
int32_t ret;
if (be_clear)
ret = cirbuff_clear_read(cbuff, outdata, outlen);
else
ret = cirbuff_noclear_read(cbuff, outdata, outlen);
return ret;
}
void cirbuff_revert(cirbuff_handle cbuff_h)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
cbuff->rpos = 0;
cbuff->wpos = 0;
cbuff->cnt = 0;
cbuff->update = 0;
return;
}
void cirbuff_destroy(cirbuff_handle cbuff_h)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
if (cbuff != NULL)
{
if (cbuff->buff != NULL)
free(cbuff->buff);
free(cbuff);
cbuff = NULL;
}
return;
}
// 以下函数为对循环缓冲区的查询
inline uint32_t cirbuff_be_empty(cirbuff_handle cbuff_h)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
return cbuff->cnt == 0 ? 1 : 0;
}
inline uint32_t cirbuff_be_full(cirbuff_handle cbuff_h)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
return cbuff->cnt == cbuff->size ? 1 : 0;
}
inline uint32_t cirbuff_data_num(cirbuff_handle cbuff_h)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
return cbuff->cnt;
}
inline uint32_t cirbuff_free_num(cirbuff_handle cbuff_h)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
return cbuff->size - cbuff->cnt;
}
inline uint32_t cirbuff_be_update(cirbuff_handle cbuff_h)
{
struct cirbuff *cbuff = (struct cirbuff *)cbuff_h;
return cbuff->update;
}