PageRenderTime 31ms CodeModel.GetById 18ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/fifo.c

https://bitbucket.org/a84/gs_public/
C | 130 lines | 103 code | 20 blank | 7 comment | 14 complexity | b872ec87eb93fb119ffaebeb7bdacee6 MD5 | raw file
  1/*
  2 * circular fifo buffer
  3 *
  4 * Author: Andrey Dyldin <and@cesbo.com>
  5 */
  6
  7#include <string.h>
  8#include <malloc.h>
  9#include "fifo.h"
 10
 11typedef unsigned char u8_t;
 12
 13typedef enum {
 14	FIFO_UNIT_READY = 0,
 15	FIFO_UNIT_SET = 1,
 16	FIFO_UNIT_GO = 2
 17} fifo_unit_status_t;
 18
 19typedef struct fifo_unit_s {
 20	struct fifo_unit_s *previous;
 21
 22	fifo_unit_status_t status;
 23	u8_t *data;
 24
 25	struct fifo_unit_s *next;
 26} fifo_unit_t;
 27
 28typedef struct {
 29	int count;
 30	int size;
 31
 32	fifo_unit_t *write;
 33	fifo_unit_t *read;
 34
 35	fifo_unit_t *data;
 36} fifo_t;
 37
 38void *fifo_init(int count, int size) {
 39	size_t unit_size = sizeof(fifo_unit_t) + size;
 40	size_t data_size = count * unit_size;
 41	size_t out_size = sizeof(fifo_t) + data_size;
 42	u8_t *out = (u8_t *)malloc(out_size);
 43	memset(out, 0, out_size);
 44
 45	fifo_t *f = (fifo_t *)out;
 46	f->count = count;
 47	f->size = size;
 48	f->data = (fifo_unit_t *)&out[sizeof(fifo_t)];
 49	f->write = f->data;
 50	f->read = f->data;
 51
 52	// mkfs :)
 53	u8_t *d = (u8_t *)f->data; // data pointer
 54	fifo_unit_t *p = NULL; // previous unit
 55	fifo_unit_t *c = (fifo_unit_t *)d; // current unit
 56	int i;
 57	for(i = 0; i < count; i++) {
 58		c->data = (u8_t *)&d[sizeof(fifo_unit_t)];
 59		d += unit_size;
 60		c->next = (fifo_unit_t *)d;
 61		c->previous = p;
 62		p = c;
 63		c = c->next;
 64	}
 65	// now c is pointer to end of allocated memory
 66	p->next = f->data;
 67	f->data->previous = p;
 68
 69	return out;
 70}
 71
 72int fifo_push(void *fifo, void *data) {
 73	fifo_t *f = (fifo_t *)fifo;
 74	u8_t *d = (u8_t *)data;
 75
 76	fifo_unit_t *c = f->write;
 77	if(c->status == FIFO_UNIT_READY) {
 78		f->write = c->next;
 79		c->status = FIFO_UNIT_SET;
 80		memcpy(c->data, d, f->size);
 81		c->status = FIFO_UNIT_GO;
 82		return f->size;
 83	}
 84
 85	return (0 - c->status);
 86}
 87
 88int fifo_pop(void *fifo, void *data) {
 89	fifo_t *f = (fifo_t *)fifo;
 90	u8_t *d = (u8_t *)data;
 91
 92	fifo_unit_t *c = f->read;
 93	if(c->status != FIFO_UNIT_GO) return 0;
 94	f->read = c->next;
 95	memcpy(d, c->data, f->size);
 96	c->status = FIFO_UNIT_READY;
 97	return f->size;
 98}
 99
100void fifo_destroy(void *fifo) {
101	if(fifo) free(fifo);
102}
103
104#if 0
105#include <stdio.h>
106int main() {
107	void *fifo = fifo_init(40, sizeof(int));
108	int i;
109	for(i = 10; i < 61; i++) {
110		int ret = fifo_push(fifo, (unsigned char *)&i);
111		if(ret != sizeof(int)) {
112			printf("fifo_push error: buffer %d:%s\n", ret
113					, (ret == -2) ? "overflow" : "unknown");
114		}
115		if(i == 30) {
116			int j;
117			for(j = 0; j < 10; j++) {
118				int z = -1;
119				fifo_pop(fifo, (unsigned char *)&z);
120				printf("pop_1:%d\n", z);
121			}
122		}
123	}
124	while(fifo_pop(fifo, (unsigned char *)&i) != 0) {
125		printf("pop_2:%d\n", i);
126	}
127	fifo_destroy(fifo);
128	return 0;
129}
130#endif // TEST