1 Star 0 Fork 0

MCai/okc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
ringBuffer.c 7.19 KB
一键复制 编辑 原始数据 按行查看 历史
MCai 提交于 2024-12-06 12:30 . misc: up
#include "ringBuffer.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
bool isFull( RingBuf *me ) {
return me->full;
}
bool isEmpty( RingBuf *me ) {
return ( !me->full && me->head == me->tail );
}
int cap( RingBuf *me ) {
return me->cap;
}
int len( RingBuf *me ) {
if ( me->full ) {
return me->cap;
}
if ( me->head >= me->tail ) {
return me->head - me->tail;
} else {
return me->cap + me->head - me->tail;
}
}
/**
* @brief 整个缓冲区内还能存放多少个元素
* [ 1 2 3 <4 5 6> 7 8 9] 这个例子left 长度为6
* @param me
* @return int
*/
int left( RingBuf *me ) {
return cap( me ) - len( me );
}
/**
* @brief 缓冲区内head到buf物理最大位置
* [ 1 2 3 <4 5 6> 7 8 9] 这个例子leftbuf 长度为3
* @param me
* @return int
*/
int leftBuf( RingBuf *me ) {
return cap( me ) - me->head;
}
int lenBuf( RingBuf *me ) {
return cap( me ) - me->tail;
}
/**
* @brief tail指针前进n个元素
*
* @param me
* @param offset
*/
void tailAdvance( RingBuf *me, uint32_t n ) {
if ( n == 0 ) return;
uint32_t min = n;
if ( len( me ) < n ) {
min = len( me );
}
if ( me->full ) {
me->full = false;
}
me->tail = ( me->tail + min ) % me->cap;
}
/**
* @brief head指针前进n个元素
*
* @param me
* @param offset
*/
void headAdvance( RingBuf *me, uint32_t n ) {
if ( n == 0 ) return;
if ( left( me ) <= n ) {
me->full = true;
}
me->head = ( me->head + n ) % me->cap;
if ( me->full ) {
me->tail = me->head;
}
}
void *headPos( RingBuf *me ) {
return (char *) me->buf + me->head * me->nbyte;
}
void *tailPos( RingBuf *me ) {
return (char *) me->buf + me->tail * me->nbyte;
}
/**
* @brief 初始化环形缓冲区
*
* @param me
* @param buf 从外部传进的数据指针
* @param num 数据个数
*/
void RingBufInit( RingBuf *me, void *buf, uint32_t num, uint32_t nbyte ) {
assert( me && buf && num && nbyte );
me->head = 0;
me->tail = 0;
me->full = false;
me->nbyte = nbyte;
me->cap = num;
me->buf = buf;
}
/**
* @brief 环形缓冲区Dump
* 尖括号之前的数据就是有效的数据
* @param me
*/
void RingBufDump( RingBuf *me ) {
printf( "len: %d, left: %d, full: %d, head: %d, tail: %d, nbyte: %d\n",
len( me ), left( me ), isFull( me ), me->head, me->tail,
me->nbyte );
for ( int i = 0; i < me->cap; i++ ) {
if ( i == me->tail ) {
if ( me->full ) {
printf( ">" );
} else {
printf( "<" );
}
}
if ( i == me->head ) {
if ( me->full ) {
printf( "<" );
} else {
printf( ">" );
}
}
if ( me->nbyte == sizeof( int ) ) {
int *dat = (int *) ( (char *) me->buf + i * me->nbyte );
printf( "%d\t", *dat );
} else if ( me->nbyte == sizeof( uint8_t ) ) {
uint8_t *dat = (uint8_t *) ( (char *) me->buf + i * me->nbyte );
printf( "%d\t", *dat );
} else if ( me->nbyte == sizeof( uint16_t ) ) {
uint16_t *dat = (uint16_t *) ( (char *) me->buf + i * me->nbyte );
printf( "%d\t", *dat );
} else {
printf( "unkown nbyte\n" );
}
if ( ( i + 1 ) % 16 == 0 ) printf( "\n" );
}
printf( "\n\n" );
}
/**
* @brief 向环形缓冲区压入数据
*
* @param me
* @param data
* @param num
* @return int
*/
int RingBufPush( RingBuf *me, void *data, uint32_t num ) {
int ret = 0;
if ( left( me ) < num ) { // 剩余空间不足
printf( "over push, have %d but need %d\n", left( me ), num );
ret = -1;
}
if ( leftBuf( me ) >= num ) { // 无需分割存储
memcpy( headPos( me ), data, num * me->nbyte );
// memcpy( &me->buf[ me->head ], data, num * sizeof( data[ 0 ] ) );
} else {
uint32_t offset = num - leftBuf( me );
memcpy( headPos( me ), data, leftBuf( me ) * me->nbyte );
memcpy( (char *) me->buf, data + leftBuf( me ) * me->nbyte,
offset * me->nbyte );
}
// me->buf[ me->head ] = data;
headAdvance( me, num );
return ret;
}
/**
* @brief 从环形缓冲区弹出指定个数的数据
*
* @param me
* @param data 接收弹出的数据,可以为NULL时只弹出,不保存数据
* @param num
* @return int
*/
int RingBufPop( RingBuf *me, void *data, uint32_t num ) {
int ret = 0;
if ( len( me ) < num ) { // 已有数据比需要pop出去要小
printf( "under pop, have %d but need %d\n", len( me ), num );
ret = -1;
return ret; // 和push不一样,len不够时不执行pop操作,只返回错误码
}
if ( data != NULL ) {
if ( lenBuf( me ) >= num ) { // 无需分割2次取出
memcpy( data, tailPos( me ), num * me->nbyte );
} else {
uint32_t offset = num - lenBuf( me );
memcpy( data, &me->buf[ me->tail ], lenBuf( me ) * me->nbyte );
memcpy( data + offset, me->buf, offset * me->nbyte );
}
}
tailAdvance( me, num );
return 0;
}
/**
* @brief 扩展功能:获取在len外的数据
*
* @param me
* @param offset
* @param data
* @return int
*/
int RingBufGet( RingBuf *me, int offset, void *data ) {
if ( len( me ) == 0 ) {
printf( "get error: len is 0\n" );
return -1;
}
if ( offset > left( me ) ) {
printf( "offset: %d is larger than left: %d\n", offset, left( me ) );
return -2;
}
if ( offset < me->tail ) {
memcpy( data, tailPos( me ) - offset * me->nbyte, me->nbyte );
} else {
memcpy( data, tailPos( me ) + ( me->cap - offset ) * me->nbyte,
me->nbyte );
}
return 0;
}
#if 0
void demo_int() {
RingBuf rb;
int buf[ 16 ] = { 0 };
int data[ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
RingBufInit( &rb, buf, sizeof( buf ) / sizeof( buf[ 0 ] ),
sizeof( buf[ 0 ] ) );
RingBufDump( &rb );
RingBufPush( &rb, data, 10 );
RingBufDump( &rb );
RingBufPush( &rb, data, 10 );
RingBufDump( &rb );
int out[ 10 ] = { 0 };
RingBufPop( &rb, out, 10 );
for ( int i = 0; i < 10; i++ ) {
printf( "%d ", out[ i ] );
if ( i == 9 ) {
printf( "\n" );
}
}
RingBufDump( &rb );
RingBufPop( &rb, out, 10 );
for ( int i = 0; i < 10; i++ ) {
printf( "%d ", out[ i ] );
if ( i == 9 ) {
printf( "\n" );
}
}
RingBufDump( &rb );
int tmp;
RingBufGet( &rb, 1, &tmp );
printf( "get %d\n", tmp );
RingBufPop( &rb, NULL, 5 );
RingBufDump( &rb );
RingBufGet( &rb, 1, &tmp );
printf( "get %d\n", tmp );
}
void demo_byte() {
RingBuf rb;
uint8_t buf[ 16 ] = { 0 };
uint8_t data[ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
RingBufInit( &rb, buf, sizeof( buf ) / sizeof( buf[ 0 ] ),
sizeof( buf[ 0 ] ) );
RingBufDump( &rb );
RingBufPush( &rb, data, 10 );
RingBufDump( &rb );
RingBufPush( &rb, data, 10 );
RingBufDump( &rb );
}
int main() {
demo_int();
// demo_push_byte();
}
#endif
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/mcai33/okc.git
git@gitee.com:mcai33/okc.git
mcai33
okc
okc
main

搜索帮助