/fifo.c
https://bitbucket.org/a84/gs_public/ · C · 130 lines · 103 code · 20 blank · 7 comment · 15 complexity · b872ec87eb93fb119ffaebeb7bdacee6 MD5 · raw file
- /*
- * circular fifo buffer
- *
- * Author: Andrey Dyldin <and@cesbo.com>
- */
- #include <string.h>
- #include <malloc.h>
- #include "fifo.h"
- typedef unsigned char u8_t;
- typedef enum {
- FIFO_UNIT_READY = 0,
- FIFO_UNIT_SET = 1,
- FIFO_UNIT_GO = 2
- } fifo_unit_status_t;
- typedef struct fifo_unit_s {
- struct fifo_unit_s *previous;
- fifo_unit_status_t status;
- u8_t *data;
- struct fifo_unit_s *next;
- } fifo_unit_t;
- typedef struct {
- int count;
- int size;
- fifo_unit_t *write;
- fifo_unit_t *read;
- fifo_unit_t *data;
- } fifo_t;
- void *fifo_init(int count, int size) {
- size_t unit_size = sizeof(fifo_unit_t) + size;
- size_t data_size = count * unit_size;
- size_t out_size = sizeof(fifo_t) + data_size;
- u8_t *out = (u8_t *)malloc(out_size);
- memset(out, 0, out_size);
- fifo_t *f = (fifo_t *)out;
- f->count = count;
- f->size = size;
- f->data = (fifo_unit_t *)&out[sizeof(fifo_t)];
- f->write = f->data;
- f->read = f->data;
- // mkfs :)
- u8_t *d = (u8_t *)f->data; // data pointer
- fifo_unit_t *p = NULL; // previous unit
- fifo_unit_t *c = (fifo_unit_t *)d; // current unit
- int i;
- for(i = 0; i < count; i++) {
- c->data = (u8_t *)&d[sizeof(fifo_unit_t)];
- d += unit_size;
- c->next = (fifo_unit_t *)d;
- c->previous = p;
- p = c;
- c = c->next;
- }
- // now c is pointer to end of allocated memory
- p->next = f->data;
- f->data->previous = p;
- return out;
- }
- int fifo_push(void *fifo, void *data) {
- fifo_t *f = (fifo_t *)fifo;
- u8_t *d = (u8_t *)data;
- fifo_unit_t *c = f->write;
- if(c->status == FIFO_UNIT_READY) {
- f->write = c->next;
- c->status = FIFO_UNIT_SET;
- memcpy(c->data, d, f->size);
- c->status = FIFO_UNIT_GO;
- return f->size;
- }
- return (0 - c->status);
- }
- int fifo_pop(void *fifo, void *data) {
- fifo_t *f = (fifo_t *)fifo;
- u8_t *d = (u8_t *)data;
- fifo_unit_t *c = f->read;
- if(c->status != FIFO_UNIT_GO) return 0;
- f->read = c->next;
- memcpy(d, c->data, f->size);
- c->status = FIFO_UNIT_READY;
- return f->size;
- }
- void fifo_destroy(void *fifo) {
- if(fifo) free(fifo);
- }
- #if 0
- #include <stdio.h>
- int main() {
- void *fifo = fifo_init(40, sizeof(int));
- int i;
- for(i = 10; i < 61; i++) {
- int ret = fifo_push(fifo, (unsigned char *)&i);
- if(ret != sizeof(int)) {
- printf("fifo_push error: buffer %d:%s\n", ret
- , (ret == -2) ? "overflow" : "unknown");
- }
- if(i == 30) {
- int j;
- for(j = 0; j < 10; j++) {
- int z = -1;
- fifo_pop(fifo, (unsigned char *)&z);
- printf("pop_1:%d\n", z);
- }
- }
- }
- while(fifo_pop(fifo, (unsigned char *)&i) != 0) {
- printf("pop_2:%d\n", i);
- }
- fifo_destroy(fifo);
- return 0;
- }
- #endif // TEST