📄 ringbuffer.c
字号:
#include <stdlib.h>#include <stdint.h>#include <string.h>#include <sys/param.h>#include <assert.h>/* * Ringbuffer implementation * * * head==tail Ringbuffer empty * head==tail-1 Ringbuffer full * * H H * 1234567 -> 1234567 * T T * * * * * * */struct ringbuffer_s { uint8_t *buffer; unsigned int atoms; unsigned int atomsize; unsigned int used; unsigned int head; unsigned int tail;};struct ringbuffer_s *ringbuffer_init(unsigned int atoms, unsigned int atomsize) { struct ringbuffer_s *rb; rb=calloc(1, sizeof(struct ringbuffer_s)); if (!rb) return NULL; rb->atoms=atoms; rb->atomsize=atomsize; rb->buffer=malloc(atomsize*atoms); if (!rb->buffer) { free(rb); return NULL; } return rb;}static int ringbuffer_headroom(struct ringbuffer_s *rb) { /* If head == tail we are either full or empty */ if (rb->used >= rb->atoms) return 0; if (rb->tail > rb->head) return rb->tail-rb->head; return rb->atoms-rb->head;}static void ringbuffer_push(struct ringbuffer_s *rb, int num) { rb->head+=num; if (rb->head >= rb->atoms) rb->head-=rb->atoms; rb->used+=num; assert(rb->used <= rb->atoms);}static int ringbuffer_add_atoms(struct ringbuffer_s *rb, uint8_t *atom, int num) { int headroom, atoms; uint8_t *dptr; headroom=ringbuffer_headroom(rb); if (!headroom) return 0; atoms=MIN(headroom, num); dptr=&rb->buffer[rb->head*rb->atomsize]; memcpy(dptr, atom, atoms*rb->atomsize); ringbuffer_push(rb, atoms); return atoms;}/* * Add atoms to the ringbuffer - We are using ringbuffer_add_atoms which * will not know about wrapping. As we know we call it twice and summ up * the result. * */int ringbuffer_add(struct ringbuffer_s *rb, uint8_t *atom, int num) { int atoms; atoms=ringbuffer_add_atoms(rb, atom, num); if (atoms >= num) return atoms; atoms+=ringbuffer_add_atoms(rb, &atom[atoms*rb->atomsize], num-atoms); return atoms;}void ringbuffer_free(struct ringbuffer_s *rb) { free(rb->buffer), free(rb);}#ifdef TEST#include <stdio.h>void dump_hex(char *prefix, uint8_t *buf, int size) { int i; unsigned char ch; char sascii[17]; char linebuffer[16*4+1]; sascii[16]=0x0; for(i=0;i<size;i++) { ch=buf[i]; if (i%16 == 0) { sprintf(linebuffer, "%04x ", i); } sprintf(&linebuffer[(i%16)*3], "%02x ", ch); if (ch >= ' ' && ch <= '}') sascii[i%16]=ch; else sascii[i%16]='.'; if (i%16 == 15) printf("%s %s %s\n", prefix, linebuffer, sascii); } /* i++ after loop */ if (i%16 != 0) { for(;i%16 != 0;i++) { sprintf(&linebuffer[(i%16)*3], " "); sascii[i%16]=' '; } printf("%s %s %s\n", prefix, linebuffer, sascii); }}void ringbuffer_dump(struct ringbuffer_s *rb) { printf("Atoms: %d AtomSize: %d Head: %d Tail: %d Used: %d\n", rb->atoms, rb->atomsize, rb->head, rb->tail, rb->used); dump_hex(" ", rb->buffer, rb->atoms*rb->atomsize); printf("\n");}int main(void ) { struct ringbuffer_s *rb=ringbuffer_init(7, 1); int i, j; uint8_t add[2]; for(i=1;i<=5;i++) { add[0]=i; add[1]=i; ringbuffer_dump(rb); printf("Trying to add 2 bytes... \n"); j=ringbuffer_add(rb, add, 2); printf("... returned j=%d\n", j); ringbuffer_dump(rb); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -