环形缓冲区

 结构示意图

#ifndef __RING_BUFFER_H__
#define __RING_BUFFER_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>

/*
缓冲区示意图:
buffer                  是缓冲区的内存起始地址
read_ofs            读数据的索引
write_ofs           写数据索引
max_len             缓冲区最大数据大小
len                         已经存入数据的大小
-------- -----------------read_ofs---------------------------write_ofs --------------------
            *****************|***************************|***********************
            ********************************************************************
            ********************************************************************
-----buffer ---------------------------------- max---------------------------------------------|

*/
typedef struct
{ 
    uint16_t read_ofs;
    uint16_t write_ofs;
    uint16_t len;
    uint16_t max;
    uint8_t *buffer;
} RingBuffer;

/*

功能:环形缓冲区初始化
参数:
    max_len 预定义缓冲区大小

*/
void InitRingBuff(RingBuffer *p_ring,uint16_t max_len);

/*
环形缓冲区释放
*/
void FreeRingBuff(RingBuffer *p_ring);

/*
 功能:
       从缓冲区读数据 并移除已经读取到的数据
参数
    pBuff       读取数据的存储控制起始地址
    len             希望读取到的数据大小
返回值:
    返回实际读取的数据
*/
int ReadRingBuff(RingBuffer *p_ring,char *pBuff, int len);


/*
 功能:
       向缓冲区写数据
参数
    pBuff       待写入数据的存储控制起始地址
    AddLen             希望写入缓冲区的到的数据大小
返回值:
    返回实际写入的数据大小 返回0 写入失败
*/
int WriteRingBuff(RingBuffer *p_ring,char *pBuff, int AddLen);
/*
 功能:
    读取指定位置的数据 ,
参数:
    index 位置都是处于有数据的位置开始

*/
uint8_t read_u8(RingBuffer *p_ring,uint16_t index);

/*
 功能:
    获取缓冲区有多少数据
返回值:
    返回缓冲区已经存储的数据大小
*/
uint16_t get_count(RingBuffer *p_ring);

#endif //RING_BUFFER

第一版代码

分为两段两次分别填充

#include "ring_buffer.h"

//环形缓冲区初始化
void InitRingBuff(RingBuffer *p_ring, uint16_t max_len)
{
    p_ring->buffer = (uint8_t*)malloc(max_len);
    memset(p_ring->buffer, 0, max_len);
    p_ring->read_ofs = 0;
    p_ring->write_ofs = 0;
    p_ring->len = 0;
    p_ring->max = max_len;
}

//环形缓冲区释放
void FreeRingBuff(RingBuffer *p_ring)
{
    if (NULL != p_ring->buffer)
    {
        free(p_ring->buffer);
    }
}

//向缓冲区写数据
int WriteRingBuff(RingBuffer *p_ring,char *pBuff, int AddLen)
{
    uint16_t len = 0;
    uint16_t remain = 0;
    if (p_ring->buffer == NULL)
    {
        printf("WriteRingBuff:RingBuff is not Init!\n");
        return 0;
    }
    //计算最多可以写入的数据长度
    if (AddLen >= p_ring->max - p_ring->len)
    {
        AddLen = p_ring->max - p_ring->len;
        printf(" kong jian bu zu\n");
    }
    //先写入到缓冲区的后半部分;在写入缓冲区的前半部分;
    if (AddLen >= p_ring->max - p_ring->len)
    {
        len = p_ring->max - p_ring->len;
        remain = AddLen - len;
    }
    else
    {
        len = AddLen;
    }
    printf("write len =%d \n", len);
    memcpy(p_ring->buffer + p_ring->write_ofs, pBuff, len);
    p_ring->len += len;
    p_ring->write_ofs += len;
    if (p_ring->write_ofs >= p_ring->max)
    {
        p_ring->write_ofs = 0;
    }

    //处理剩余没有写入的数据
    if (remain > 0 && p_ring->max - p_ring->len > 0)
    {
        memcpy(p_ring->buffer, pBuff, len);
        p_ring->len += len;
        p_ring->write_ofs = len;
    }
    if (p_ring->write_ofs >= p_ring->max)
    {
        p_ring->write_ofs = 0;
    }

    printf("write : ");
    for (uint16_t i = 0; i < p_ring->max; i++)
    {
        printf("%02x ", p_ring->buffer[i]);
    }
    printf("\n ");
    printf("read = %d write =  %d  len = %d\n", p_ring->read_ofs, p_ring->write_ofs, p_ring->len);
    return AddLen;
}
/*
    从缓冲区读数据 并移除已经读取到的数据
*/
int ReadRingBuff(RingBuffer *p_ring,char *pBuff, int read_len)
{
    uint16_t len = 0;
    uint16_t alread_read = 0;
    uint16_t remain = 0;
    if (p_ring->buffer == NULL)
    {
        printf("don't init RingBuffer\n");
        return 0;
    }
    if (read_len > p_ring->len)
    {
        read_len = p_ring->len;
        printf("read data only \n");
    }

    if (read_len > p_ring->max - p_ring->read_ofs)
    {
        len = p_ring->max - p_ring->read_ofs;
        remain = read_len - len;
    }
    else
    {
        len = read_len;
    }
    memcpy(pBuff, p_ring->buffer + p_ring->read_ofs, len);
    p_ring->read_ofs += len;
    p_ring->len -= len;
    alread_read += len;
    if (p_ring->read_ofs >= p_ring->max)
    {
        p_ring->read_ofs = 0;
    }

    //处理尾端没有一次行读取完的
    if (remain > 0)
    {
        memcpy(pBuff + alread_read, p_ring->buffer + p_ring->read_ofs, remain);
        p_ring->read_ofs += remain;
        p_ring->len -= remain;
    }
    if (p_ring->len == 0)
    {
        p_ring->read_ofs = 0;
        p_ring->write_ofs = 0;
    }

    printf("read : ");
    for (uint16_t i = 0; i < read_len; i++)
    {
        printf("%02x ", pBuff[i]);
    }
    printf("\n ");
    printf("read = %d write =  %d  len = %d\n", p_ring->read_ofs, p_ring->write_ofs, p_ring->len);

    return read_len;
}


/*
    获取缓冲区有多少数据
*/
uint16_t get_count(RingBuffer *p_ring)
{
    return p_ring->len;
}

/*
    读取指定位置的数据 ,位置都是处于有数据的位置开始

*/
uint8_t read_u8(RingBuffer *p_ring,uint16_t index)
{
    uint16_t   real_index=0;
    if(index>p_ring->len-1)
    {
        printf("index error\n");

    }
    real_index = (p_ring->read_ofs+index)%p_ring->max;
    return p_ring->buffer[real_index];

}


第二版代码

使用取余的方式自动由尾到头

#include "ring_buffer.h"

//环形缓冲区初始化
void InitRingBuff(RingBuffer *p_ring, uint16_t max_len)
{
    p_ring->buffer = (uint8_t *)malloc(max_len);
    memset(p_ring->buffer, 0, max_len);
    p_ring->read_ofs = 0;
    p_ring->write_ofs = 0;
    p_ring->len = 0;
    p_ring->max = max_len;
}

//环形缓冲区释放
void FreeRingBuff(RingBuffer *p_ring)
{
    if (NULL != p_ring->buffer)
    {
        free(p_ring->buffer);
    }
}

//向缓冲区写数据
int WriteRingBuff(RingBuffer *p_ring, char *pBuff, int AddLen)
{
    uint16_t len = 0;
    uint16_t remain = 0;
    if (p_ring->buffer == NULL)
    {
        printf("WriteRingBuff:RingBuff is not Init!\n");
        return 0;
    }
    //计算最多可以写入的数据长度
    if (AddLen >= p_ring->max - p_ring->len)
    {
        AddLen = p_ring->max - p_ring->len;
        printf(" kong jian bu zu %d\n",AddLen);
    }
    for (uint16_t i = 0; i < AddLen; i++)
    {
        
       
        p_ring->buffer[p_ring->write_ofs] = pBuff[i];
        p_ring->write_ofs = (++p_ring->write_ofs)  % p_ring->max;
    }
    p_ring->len += AddLen;
 
    printf("write : ");
    for (uint16_t i = 0; i < p_ring->max; i++)
    {
        printf("%02x ", p_ring->buffer[i]);
    }
    printf("\n ");
    printf("read = %d write =  %d  len = %d\n", p_ring->read_ofs, p_ring->write_ofs, p_ring->len);
    return AddLen;
}
/*
    从缓冲区读数据 并移除已经读取到的数据
*/
int ReadRingBuff(RingBuffer *p_ring, char *pBuff, int read_len)
{
    uint16_t len = 0;
    uint16_t alread_read = 0;
    uint16_t remain = 0;
    if (p_ring->buffer == NULL)
    {
        printf("don't init RingBuffer\n");
        return 0;
    }
    if (read_len > p_ring->len)
    {
        read_len = p_ring->len;
        printf("read data only \n");
    }
    for(uint16_t i=0;i<read_len;i++)
    {
        pBuff[i] = p_ring->buffer[p_ring->read_ofs];
        p_ring->read_ofs=(++p_ring->read_ofs)%p_ring->max;
        
    }
    p_ring->len-=read_len;

    printf("read : ");
    for (uint16_t i = 0; i < read_len; i++)
    {
        printf("%02x ", pBuff[i]);
    }
    printf("\n ");
    printf("read = %d write =  %d  len = %d\n", p_ring->read_ofs, p_ring->write_ofs, p_ring->len);

    return read_len;
}

/*
    获取缓冲区有多少数据
*/
uint16_t get_count(RingBuffer *p_ring)
{
    return p_ring->len;
}

/*
    读取指定位置的数据 ,位置都是处于有数据的位置开始

*/
uint8_t read_u8(RingBuffer *p_ring, uint16_t index)
{
    uint16_t real_index = 0;
    if (index > p_ring->len - 1)
    {
        printf("index error\n");
    }
    real_index = (p_ring->read_ofs + index) % p_ring->max;
    return p_ring->buffer[real_index];
}

测试代码

#include "ring_buffer.h"


int main()
{
    RingBuffer ring;
    InitRingBuff(&ring, 7);
    uint8_t readBuffer[8];
    WriteRingBuff(&ring, "123456789", 9);
    WriteRingBuff(&ring, "!@#$", 4);
    ReadRingBuff(&ring, readBuffer, 3);
    WriteRingBuff(&ring, "abcd", 4);

    //ReadRingBuff(readBuffer,10);
    printf("main read : ");
    for (uint16_t i = 0; i < get_count(&ring); i++)
    {
        printf("%02x ", read_u8(&ring, i));
    }
    printf("\n ");

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Car12

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

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

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

打赏作者

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

抵扣说明:

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

余额充值