ringbuffer.c (4003B)
1 /** 2 * @file ringbuffer.c 3 * @author Adrian STEINER (steia19@bfh.ch) 4 * @brief Base ringbuffer header file for handling an unspecific data in a ring buffer design 5 * @version 0.2 6 * @date 2024-03-15 7 * @date 2025-02-13 8 * 9 * @copyright (C) 2025 Adrian STEINER 10 * This program is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation, either version 3 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program. If not, see <https: //www.gnu.org/licenses/>. 22 * 23 */ 24 25 #include "ringbuffer.h" 26 #include <stddef.h> 27 #include <string.h> 28 29 ringbuffer_StatusType 30 ringbuffer_init(ringbuffer_handler *rbHandler, void *buffer, uint32_t length, uint32_t elmSize) { 31 if (rbHandler == NULL || buffer == NULL || length == 0 || elmSize == 0) { 32 return RINGBUFFER_ARGUMENT_ERROR; 33 } 34 rbHandler->dataBuffer = buffer; 35 rbHandler->length = length; 36 rbHandler->elmSize = elmSize; 37 38 // Initialise head and tail positions 39 rbHandler->headPos = 0; 40 rbHandler->tailPos = 0; 41 42 return RINGBUFFER_OK; 43 } 44 45 void *ringbuffer_destroy(ringbuffer_handler *rbHandler) { 46 if (rbHandler == NULL) { 47 return NULL; 48 } 49 void *bufferArray = rbHandler->dataBuffer; 50 rbHandler->dataBuffer = NULL; 51 return bufferArray; 52 } 53 54 ringbuffer_StatusType ringbuffer_enqueue(ringbuffer_handler *rbHandler, void *data) { 55 if (rbHandler == NULL || data == NULL) { 56 return RINGBUFFER_ARGUMENT_ERROR; 57 } 58 59 if (ringbuffer_isFull(rbHandler)) { 60 return RINGBUFFER_OVERFLOW; 61 } 62 63 /* Insert element */ 64 if ( 65 NULL == memcpy( 66 data, 67 (void *)((uint8_t *)rbHandler->dataBuffer + (rbHandler->tailPos * rbHandler->elmSize)), 68 rbHandler->elmSize)) { 69 return RINGBUFFER_ERROR; 70 } 71 rbHandler->tailPos = (rbHandler->tailPos + 1) % rbHandler->length; 72 return RINGBUFFER_OK; 73 } 74 75 ringbuffer_StatusType ringbuffer_dequeue(ringbuffer_handler *rbHandler, void **data) { 76 if (rbHandler == NULL || data == NULL) { 77 return RINGBUFFER_ARGUMENT_ERROR; 78 } 79 80 if (ringbuffer_isEmpty(rbHandler)) { 81 return RINGBUFFER_EMPTY; 82 } 83 84 (*data) = (uint8_t *)rbHandler->dataBuffer + (rbHandler->headPos * rbHandler->elmSize); 85 86 rbHandler->headPos = (rbHandler->headPos + 1) % rbHandler->length; 87 88 return RINGBUFFER_OK; 89 } 90 91 void *ringbuffer_peek(const ringbuffer_handler *rbHandler) { 92 if (rbHandler == NULL) { 93 return NULL; 94 } 95 if (ringbuffer_isEmpty(rbHandler)) { 96 return NULL; 97 } 98 return (void *)((uint8_t *)rbHandler->dataBuffer + rbHandler->headPos * rbHandler->elmSize); 99 } 100 101 uint32_t ringbuffer_size(const ringbuffer_handler *rbHandler) { 102 if (rbHandler == NULL) { 103 return 0; 104 } 105 // Check if a overflow of array is recognised 106 if (rbHandler->headPos > rbHandler->tailPos) { 107 return (rbHandler->length - rbHandler->headPos + rbHandler->tailPos); 108 } 109 // No overflow, calculate back - front 110 else { 111 return rbHandler->headPos - rbHandler->tailPos; 112 } 113 } 114 115 bool ringbuffer_isFull(const ringbuffer_handler *rbHandler) { 116 if (rbHandler == NULL) { 117 return false; 118 } 119 120 if ((rbHandler->tailPos + 1) % rbHandler->length == rbHandler->headPos) { 121 return true; 122 } else { 123 return false; 124 } 125 } 126 127 bool ringbuffer_isEmpty(const ringbuffer_handler *rbHandler) { 128 if (rbHandler == NULL) { 129 return false; 130 } 131 132 if (rbHandler->tailPos == rbHandler->headPos) { 133 return true; 134 } else { 135 return false; 136 } 137 } 138 139 ringbuffer_StatusType ringbuffer_clear(ringbuffer_handler *rbHandler) { 140 if (rbHandler == NULL) { 141 return RINGBUFFER_ARGUMENT_ERROR; 142 } 143 rbHandler->tailPos = rbHandler->headPos; 144 return RINGBUFFER_OK; 145 }