Ring buffer
#ifndef __RING_BUFFER_H__ #define __RING_BUFFER_H__ //------------------------------------------------------------------------------ // External functions //------------------------------------------------------------------------------ void BSP_Lock( void ); void BSP_Unlock( void ); typedef struct { unsigned char * buffer; unsigned int capacity; unsigned int pointer; unsigned int count; } ring_buffer_t; ring_buffer_t *ring_buffer_create( unsigned int size ); void ring_buffer_delete( ring_buffer_t *ring_buffer ); void ring_buffer_init( ring_buffer_t *ring_buffer, unsigned char * buffer, unsigned int capacity ); void ring_buffer_clear( ring_buffer_t *ring_buffer ); unsigned int ring_buffer_readable( ring_buffer_t *ring_buffer ); unsigned int ring_buffer_writable( ring_buffer_t *ring_buffer ); void ring_buffer_flush( ring_buffer_t *ring_buffer, unsigned int bytes ); unsigned int ring_buffer_read( ring_buffer_t *ring_buffer, unsigned char *data, unsigned int length ); unsigned int ring_buffer_write( ring_buffer_t *ring_buffer, const unsigned char *data, unsigned int length ); unsigned int ring_buffer_full( ring_buffer_t *ring_buffer ); unsigned int ring_buffer_empty( ring_buffer_t *ring_buffer ); #endif /* __RING_BUFFER_H__ */
#include "ring_buffer.h" #include <stdlib.h> #include <string.h> unsigned int ring_buffer_readable( ring_buffer_t *ring_buffer ) { return ring_buffer->count; } unsigned int ring_buffer_writable( ring_buffer_t *ring_buffer ) { return ring_buffer->capacity - ring_buffer->count; } unsigned int ring_buffer_full( ring_buffer_t *ring_buffer ) { return ring_buffer->count == ring_buffer->capacity; } unsigned int ring_buffer_empty( ring_buffer_t *ring_buffer ) { return ring_buffer->count == 0; } unsigned int ring_buffer_read( ring_buffer_t *ring_buffer, unsigned char *data, unsigned int length ) { unsigned int buffer_readable = ring_buffer_readable( ring_buffer ); unsigned int bytes_read = length; if ( bytes_read > buffer_readable ) bytes_read = buffer_readable; if ( bytes_read == 0 ) return 0; // -----------RRRRRRRRRRRR if ( ring_buffer->pointer + bytes_read <= ring_buffer->capacity ) memcpy( data, ring_buffer->buffer + ring_buffer->pointer, bytes_read ); else // RRRRRR--------------RRRRR { unsigned int upper = ring_buffer->capacity - ring_buffer->pointer; unsigned int lower = bytes_read - upper; memcpy( data, ring_buffer->buffer + ring_buffer->pointer, upper ); memcpy( data + upper, ring_buffer->buffer, lower ); } BSP_Lock( ); ring_buffer->pointer = ( ring_buffer->pointer + bytes_read ) % ring_buffer->capacity; ring_buffer->count -= bytes_read; BSP_Unlock( ); return bytes_read; } unsigned int ring_buffer_write( ring_buffer_t *ring_buffer, const unsigned char *data, unsigned int length ) { unsigned int bytes_written = length; unsigned int buffer_writable = ring_buffer_writable( ring_buffer ); if ( bytes_written > buffer_writable ) bytes_written = buffer_writable; if ( bytes_written == 0 ) return 0; unsigned int write_position = ( ring_buffer->pointer + ring_buffer->count ) % ring_buffer->capacity; // --------WWWWWWWW--- if ( write_position + bytes_written <= ring_buffer->capacity ) memcpy( ring_buffer->buffer + write_position, data, bytes_written ); else // WWWWWWW-------WWWW { unsigned int upper = ring_buffer->capacity - write_position; unsigned int lower = bytes_written - upper; memcpy( ring_buffer->buffer + write_position, data, upper ); memcpy( ring_buffer->buffer, data + upper, lower ); } BSP_Lock( ); ring_buffer->count += bytes_written; BSP_Unlock( ); return bytes_written; } void ring_buffer_flush( ring_buffer_t *ring_buffer, unsigned int length ) { // we can't flush more bytes than there are BSP_Lock( ); if ( length > (unsigned int) ring_buffer->count ) length = ring_buffer->count; ring_buffer->count -= length; ring_buffer->pointer = ( ring_buffer->pointer + length ); ring_buffer->pointer %= ring_buffer->capacity; BSP_Unlock( ); } void ring_buffer_clear( ring_buffer_t *ring_buffer ) { BSP_Lock( ); ring_buffer->count = 0; ring_buffer->pointer = 0; BSP_Unlock( ); } void ring_buffer_init( ring_buffer_t *ring_buffer, unsigned char * buffer, unsigned int capacity ) { ring_buffer->buffer = buffer; ring_buffer->capacity = capacity; ring_buffer_clear( ring_buffer ); } ring_buffer_t * ring_buffer_create( unsigned int size ) { void * p = malloc( sizeof(ring_buffer_t) + size ); ring_buffer_t *ring_buffer = (ring_buffer_t *) p; if ( ring_buffer == NULL ) return NULL; ring_buffer->capacity = size; ring_buffer_clear( ring_buffer ); return ring_buffer; } void ring_buffer_delete( ring_buffer_t *ring_buffer ) { free( ring_buffer ); }