liubin | 281ac46 | 2023-07-19 14:22:54 +0800 | [diff] [blame^] | 1 | #include <inttypes.h> |
| 2 | #include <stddef.h> |
| 3 | #include <assert.h> |
| 4 | /** |
| 5 | * @file |
| 6 | * Prototypes and structures for the ring buffer module. |
| 7 | */ |
| 8 | |
| 9 | #ifndef RINGBUFFER_H |
| 10 | #define RINGBUFFER_H |
| 11 | |
| 12 | #ifdef __cplusplus |
| 13 | extern "C" |
| 14 | { |
| 15 | #endif |
| 16 | |
| 17 | #define RING_BUFFER_ASSERT(x) assert(x) |
| 18 | |
| 19 | /** |
| 20 | * Checks if the buffer_size is a power of two. |
| 21 | * Due to the design only <tt> RING_BUFFER_SIZE-1 </tt> items |
| 22 | * can be contained in the buffer. |
| 23 | * buffer_size must be a power of two. |
| 24 | */ |
| 25 | #define RING_BUFFER_IS_POWER_OF_TWO(buffer_size) ((buffer_size & (buffer_size - 1)) == 0) |
| 26 | |
| 27 | /** |
| 28 | * The type which is used to hold the size |
| 29 | * and the indicies of the buffer. |
| 30 | */ |
| 31 | typedef size_t ring_buffer_size_t; |
| 32 | |
| 33 | /** |
| 34 | * Used as a modulo operator |
| 35 | * as <tt> a % b = (a & (b − 1)) </tt> |
| 36 | * where \c a is a positive index in the buffer and |
| 37 | * \c b is the (power of two) size of the buffer. |
| 38 | */ |
| 39 | #define RING_BUFFER_MASK(rb) (rb->buffer_mask) |
| 40 | |
| 41 | /** |
| 42 | * Simplifies the use of <tt>struct ring_buffer_t</tt>. |
| 43 | */ |
| 44 | typedef struct ring_buffer_t ring_buffer_t; |
| 45 | |
| 46 | /** |
| 47 | * Structure which holds a ring buffer. |
| 48 | * The buffer contains a buffer array |
| 49 | * as well as metadata for the ring buffer. |
| 50 | */ |
| 51 | struct ring_buffer_t { |
| 52 | /** Buffer memory. */ |
| 53 | char *buffer; |
| 54 | /** Buffer mask. */ |
| 55 | ring_buffer_size_t buffer_mask; |
| 56 | /** Index of tail. */ |
| 57 | ring_buffer_size_t tail_index; |
| 58 | /** Index of head. */ |
| 59 | ring_buffer_size_t head_index; |
| 60 | }; |
| 61 | |
| 62 | /** |
| 63 | * Initializes the ring buffer pointed to by <em>buffer</em>. |
| 64 | * This function can also be used to empty/reset the buffer. |
| 65 | * @param buffer The ring buffer to initialize. |
| 66 | * @param buf The buffer allocated for the ringbuffer. |
| 67 | * @param buf_size The size of the allocated ringbuffer. |
| 68 | */ |
| 69 | void ring_buffer_init(ring_buffer_t *buffer, char *buf, size_t buf_size); |
| 70 | |
| 71 | /** |
| 72 | * Adds a byte to a ring buffer. |
| 73 | * @param buffer The buffer in which the data should be placed. |
| 74 | * @param data The byte to place. |
| 75 | */ |
| 76 | void ring_buffer_queue(ring_buffer_t *buffer, char data); |
| 77 | |
| 78 | /** |
| 79 | * Adds an array of bytes to a ring buffer. |
| 80 | * @param buffer The buffer in which the data should be placed. |
| 81 | * @param data A pointer to the array of bytes to place in the queue. |
| 82 | * @param size The size of the array. |
| 83 | */ |
| 84 | void ring_buffer_queue_arr(ring_buffer_t *buffer, const char *data, ring_buffer_size_t size); |
| 85 | |
| 86 | /** |
| 87 | * Returns the oldest byte in a ring buffer. |
| 88 | * @param buffer The buffer from which the data should be returned. |
| 89 | * @param data A pointer to the location at which the data should be placed. |
| 90 | * @return 1 if data was returned; 0 otherwise. |
| 91 | */ |
| 92 | uint8_t ring_buffer_dequeue(ring_buffer_t *buffer, char *data); |
| 93 | |
| 94 | /** |
| 95 | * Returns the <em>len</em> oldest bytes in a ring buffer. |
| 96 | * @param buffer The buffer from which the data should be returned. |
| 97 | * @param data A pointer to the array at which the data should be placed. |
| 98 | * @param len The maximum number of bytes to return. |
| 99 | * @return The number of bytes returned. |
| 100 | */ |
| 101 | ring_buffer_size_t ring_buffer_dequeue_arr(ring_buffer_t *buffer, char *data, ring_buffer_size_t len); |
| 102 | /** |
| 103 | * Peeks a ring buffer, i.e. returns an element without removing it. |
| 104 | * @param buffer The buffer from which the data should be returned. |
| 105 | * @param data A pointer to the location at which the data should be placed. |
| 106 | * @param index The index to peek. |
| 107 | * @return 1 if data was returned; 0 otherwise. |
| 108 | */ |
| 109 | uint8_t ring_buffer_peek(ring_buffer_t *buffer, char *data, ring_buffer_size_t index); |
| 110 | |
| 111 | |
| 112 | /** |
| 113 | * Returns whether a ring buffer is empty. |
| 114 | * @param buffer The buffer for which it should be returned whether it is empty. |
| 115 | * @return 1 if empty; 0 otherwise. |
| 116 | */ |
| 117 | uint8_t ring_buffer_is_empty(ring_buffer_t *buffer); |
| 118 | /** |
| 119 | * Returns whether a ring buffer is full. |
| 120 | * @param buffer The buffer for which it should be returned whether it is full. |
| 121 | * @return 1 if full; 0 otherwise. |
| 122 | */ |
| 123 | uint8_t ring_buffer_is_full(ring_buffer_t *buffer); |
| 124 | |
| 125 | /** |
| 126 | * Returns the number of items in a ring buffer. |
| 127 | * @param buffer The buffer for which the number of items should be returned. |
| 128 | * @return The number of items in the ring buffer. |
| 129 | */ |
| 130 | ring_buffer_size_t ring_buffer_num_items(ring_buffer_t *buffer); |
| 131 | |
| 132 | void ring_buffer_clean(ring_buffer_t *buffer); |
| 133 | |
| 134 | #ifdef __cplusplus |
| 135 | } |
| 136 | #endif |
| 137 | |
| 138 | #endif /* RINGBUFFER_H */ |