简洁C语言实现FIFO

前言

最近用到两个FIFO实现,这个实现比较简洁,利用了无符号数的特性,掩码的运用十分巧妙,分享一下。

源码

ringbuffer.h:

/*******************************************************************************
* @File 	  : ringbuffer.h
* @Brief	  : This file provides all the fifo functions.
********************************************************************************
* @Attention:
* Non
*
*******************************************************************************/
 
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _RINGBUFFER_H
#define _RINGBUFFER_H
 

#ifdef __cplusplus
 extern "C" {
#endif
	 
/* Includes ------------------------------------------------------------------*/
/* Define --------------------------------------------------------------------*/
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif		
 
#define is_power_of_2(x)	((x) != 0 && (((x) & ((x) - 1)) == 0))
		
/* Private typedef -----------------------------------------------------------*/
typedef struct fifo {
	unsigned int	in;
	unsigned int	out;
	unsigned int	mask;
	unsigned char *data;
}fifo_t; 
 
/* Function prototypes -------------------------------------------------------*/
extern unsigned int fifo_used(fifo_t *fifo);
extern signed int fifo_alloc(fifo_t *fifo, unsigned int size);
extern void         fifo_free(fifo_t *fifo);
extern int          fifo_init(fifo_t *fifo, unsigned char *buffer,	unsigned int size);
extern unsigned int fifo_in(fifo_t *fifo, unsigned char *buf, unsigned int len);
extern unsigned int fifo_out(fifo_t *fifo,	unsigned char *buf, unsigned int len);
	 
#ifdef __cplusplus
}
#endif
 
#endif

ringbuffer.c:

/******************************************************************************
* @File 	  : ringbuffer.c
* @Author   : cqx
* @Version  : V0.0.1
* @Date 	  : 29-november-2016
* @Brief	  : This file provides all the fifo functions.
******************************************************************************
* @Attention:
* 
*
******************************************************************************/
/* Includes -----------------------------------------------------------------*/
#include "ringbuffer.h"
#include "stdlib.h"
#include "string.h"
 
/* Variables -----------------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/******************************************************************************/
 
/*
 * internal helper to calculate the unused elements in a fifo
 */
static  unsigned int fifo_unused(struct fifo *fifo)
{
  return (fifo->mask + 1) - (fifo->in - fifo->out);
}
 
unsigned int fifo_used(struct fifo *fifo)
{
  return (fifo->in - fifo->out);
}
 
signed int fifo_alloc(struct fifo *fifo, unsigned int size)
{	
/*
	 * round down to the next power of 2, since our 'let the indices
	 * wrap' technique works only in this case.
	 */
	if (!is_power_of_2(size))
		return -1;
 
	fifo->in = 1;
	fifo->out = 1;
	
	if (size < 2){
		fifo->data = NULL;
		fifo->mask = 0;
		return -1;
	}
	fifo->data = malloc(size);
	
	if (!fifo->data){
		fifo->mask = 0;
		return -1;
	}	
	fifo->mask = size - 1;
  
  return 0;
}
 
void fifo_free(struct fifo *fifo)
{
	free(fifo->data);
	fifo->in = 0;
	fifo->out = 0;
	fifo->data = NULL;
	fifo->mask = 0;
}
 
int fifo_init(struct fifo *fifo, unsigned char *buffer, unsigned int size)
{
	if (!is_power_of_2(size))
		return -1;
 
	fifo->in = 0;
	fifo->out = 0;
	fifo->data = buffer;
 
	if (size < 2) {
		fifo->mask = 0;
		return -1;
	}
	fifo->mask = size - 1;
 
	return 0;
}
 
static void fifo_copy_in(struct fifo *fifo, unsigned char *src, unsigned int len, unsigned int off)
{
	unsigned int size = fifo->mask + 1;
	unsigned int l;
 
	off &= fifo->mask;
 
	l = min(len, size - off);
 
	memcpy(fifo->data + off, src, l);
	memcpy(fifo->data, src + l, len - l);
}
 
unsigned int fifo_in(struct fifo *fifo, unsigned char *buf, unsigned int len)
{
	unsigned int l;
 
	l = fifo_unused(fifo);
	if (len > l)
		len = l;
 
	fifo_copy_in(fifo, buf, len, fifo->in);
	fifo->in += len;
	
	return len;
}
 
static void fifo_copy_out(struct fifo *fifo, unsigned char *dst, unsigned int len, unsigned int off)
{
	unsigned int size = fifo->mask + 1;
	unsigned int l;
 
	off &= fifo->mask;
	l = min(len, size - off);
 
	memcpy(dst, fifo->data + off, l);
	memcpy(dst + l, fifo->data, len - l);
}
 
unsigned int fifo_out_peek(struct fifo *fifo, unsigned char *buf, unsigned int len)
{
	unsigned int l;
 
	l = fifo->in - fifo->out;
	if (len > l)
		len = l;
 
	fifo_copy_out(fifo, buf, len, fifo->out);
	return len;
}
 
unsigned int fifo_out(struct fifo *fifo, unsigned char *buf, unsigned int len)
{
	len = fifo_out_peek(fifo, buf, len);
	fifo->out += len;
	return len;
}

你可能感兴趣的:(code)