|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2015 Kaspar Schleiser <[email protected]> |
| 3 | + * SPDX-FileCopyrightText: 2025 Karl Fessel <[email protected]> ML!PA Consulting GmbH |
| 4 | + * SPDX-License-Identifier: LGPL-2.1-only |
| 5 | + */ |
| 6 | + |
| 7 | +#pragma once |
| 8 | + |
| 9 | +/** |
| 10 | + * @ingroup sys_tsrb |
| 11 | + * @brief Thread Unsafe access to Thread-safe ringbuffer |
| 12 | + * @{ |
| 13 | + * |
| 14 | + * @attention use only if you ensurred thread safety otherwise |
| 15 | + * e.g.: by an irq guard |
| 16 | + * @file |
| 17 | + * @brief Thread-unsafe ringbuffer interface definition |
| 18 | + * |
| 19 | + * @author Kaspar Schleiser <[email protected]> |
| 20 | + * @author Karl Fessel <[email protected]> |
| 21 | + */ |
| 22 | + |
| 23 | +#include "tsrb.h" |
| 24 | + |
| 25 | +#ifdef __cplusplus |
| 26 | +extern "C" { |
| 27 | +#endif |
| 28 | + |
| 29 | +/** |
| 30 | + * @brief Clear a tsrb. |
| 31 | + * @attention use only if you ensurred thread safety otherwise |
| 32 | + * @param[out] rb Ringbuffer to operate on |
| 33 | + */ |
| 34 | +static inline void turb_clear(tsrb_t *rb) |
| 35 | +{ |
| 36 | + rb->reads = rb->writes; |
| 37 | +} |
| 38 | + |
| 39 | +/** |
| 40 | + * @brief Test if the tsrb is empty. |
| 41 | + * @attention use only if you ensurred thread safety otherwise |
| 42 | + * @param[in] rb Ringbuffer to operate on |
| 43 | + * @return 0 if not empty |
| 44 | + * @return 1 otherwise |
| 45 | + */ |
| 46 | +static inline int turb_empty(const tsrb_t *rb) |
| 47 | +{ |
| 48 | + int retval = (rb->reads == rb->writes); |
| 49 | + return retval; |
| 50 | +} |
| 51 | + |
| 52 | +/** |
| 53 | + * @brief Get number of bytes available for reading |
| 54 | + * @attention use only if you ensurred thread safety otherwise |
| 55 | + * @param[in] rb Ringbuffer to operate on |
| 56 | + * @return nr of available bytes |
| 57 | + */ |
| 58 | +static inline unsigned int turb_avail(const tsrb_t *rb) |
| 59 | +{ |
| 60 | + unsigned retval = (rb->writes - rb->reads); |
| 61 | + return retval; |
| 62 | +} |
| 63 | + |
| 64 | +/** |
| 65 | + * @brief Test if the tsrb is full |
| 66 | + * @attention use only if you ensurred thread safety otherwise |
| 67 | + * @param[in] rb Ringbuffer to operate on |
| 68 | + * @return 0 if not full |
| 69 | + * @return 1 otherwise |
| 70 | + */ |
| 71 | +static inline int turb_full(const tsrb_t *rb) |
| 72 | +{ |
| 73 | + int retval = (rb->writes - rb->reads) == rb->size; |
| 74 | + return retval; |
| 75 | +} |
| 76 | + |
| 77 | +/** |
| 78 | + * @brief Get free space in ringbuffer |
| 79 | + * @attention use only if you ensurred thread safety otherwise |
| 80 | + * @param[in] rb Ringbuffer to operate on |
| 81 | + * @return nr of available bytes |
| 82 | + */ |
| 83 | +static inline unsigned int turb_free(const tsrb_t *rb) |
| 84 | +{ |
| 85 | + unsigned int retval = (rb->size - rb->writes + rb->reads); |
| 86 | + return retval; |
| 87 | +} |
| 88 | + |
| 89 | +#ifndef DOXYGEN |
| 90 | +/* these are internal function */ |
| 91 | +static inline void _turb_push(tsrb_t *rb, uint8_t c) |
| 92 | +{ |
| 93 | + rb->buf[rb->writes++ & (rb->size - 1)] = c; |
| 94 | +} |
| 95 | + |
| 96 | +static inline uint8_t _turb_pop(tsrb_t *rb) |
| 97 | +{ |
| 98 | + return rb->buf[rb->reads++ & (rb->size - 1)]; |
| 99 | +} |
| 100 | + |
| 101 | +static inline uint8_t _turb_peek(tsrb_t *rb, unsigned int idx) |
| 102 | +{ |
| 103 | + return rb->buf[(rb->reads + idx) & (rb->size - 1)]; |
| 104 | +} |
| 105 | +#endif |
| 106 | + |
| 107 | +/** |
| 108 | + * @brief Get a byte from ringbuffer |
| 109 | + * @attention use only if you ensurred thread safety otherwise |
| 110 | + * @param[in] rb Ringbuffer to operate on |
| 111 | + * @return >=0 byte that has been read |
| 112 | + * @return -1 if no byte available |
| 113 | + */ |
| 114 | +static inline int turb_get_one(tsrb_t *rb) |
| 115 | +{ |
| 116 | + int retval = -1; |
| 117 | + if (!turb_empty(rb)) { |
| 118 | + retval = _turb_pop(rb); |
| 119 | + } |
| 120 | + return retval; |
| 121 | +} |
| 122 | + |
| 123 | +/** |
| 124 | + * @brief Get a byte from ringbuffer, without removing it |
| 125 | + * @attention use only if you ensurred thread safety otherwise |
| 126 | + * @param[in] rb Ringbuffer to operate on |
| 127 | + * @return >=0 byte that has been read |
| 128 | + * @return -1 if no byte available |
| 129 | + */ |
| 130 | +static inline int turb_peek_one(tsrb_t *rb) |
| 131 | +{ |
| 132 | + int retval = -1; |
| 133 | + if (!turb_empty(rb)) { |
| 134 | + retval = _turb_peek(rb, 0); |
| 135 | + } |
| 136 | + return retval; |
| 137 | +} |
| 138 | + |
| 139 | +/** |
| 140 | + * @brief Get bytes from ringbuffer |
| 141 | + * @attention use only if you ensurred thread safety otherwise |
| 142 | + * @param[in] rb Ringbuffer to operate on |
| 143 | + * @param[out] dst buffer to write to |
| 144 | + * @param[in] n max number of bytes to write to @p dst |
| 145 | + * @return nr of bytes written to @p dst |
| 146 | + */ |
| 147 | +static inline int turb_get(tsrb_t *rb, uint8_t *dst, size_t n) |
| 148 | +{ |
| 149 | + size_t cnt = 0; |
| 150 | + while (n-- && !turb_empty(rb)) { |
| 151 | + *dst++ = _turb_pop(rb); |
| 152 | + cnt++; |
| 153 | + } |
| 154 | + return (int) cnt; |
| 155 | +} |
| 156 | + |
| 157 | +/** |
| 158 | + * @brief Get bytes from ringbuffer, without removing them |
| 159 | + * @attention use only if you ensurred thread safety otherwise |
| 160 | + * @param[in] rb Ringbuffer to operate on |
| 161 | + * @param[out] dst buffer to write to |
| 162 | + * @param[in] n max number of bytes to write to @p dst |
| 163 | + * @return nr of bytes written to @p dst |
| 164 | + */ |
| 165 | +static inline int turb_peek(tsrb_t *rb, uint8_t *dst, size_t n) |
| 166 | +{ |
| 167 | + size_t idx = 0; |
| 168 | + unsigned int avail = turb_avail(rb); |
| 169 | + while (idx < n && idx != avail) { |
| 170 | + *dst++ = _turb_peek(rb, idx++); |
| 171 | + } |
| 172 | + return (int) idx; |
| 173 | +} |
| 174 | + |
| 175 | +/** |
| 176 | + * @brief Drop bytes from ringbuffer |
| 177 | + * @attention use only if you ensurred thread safety otherwise |
| 178 | + * @param[in] rb Ringbuffer to operate on |
| 179 | + * @param[in] n max number of bytes to drop |
| 180 | + * @return nr of bytes dropped |
| 181 | + */ |
| 182 | +static inline int turb_drop(tsrb_t *rb, size_t n) |
| 183 | +{ |
| 184 | + size_t cnt = 0; |
| 185 | + while (n-- && !turb_empty(rb)) { |
| 186 | + _turb_pop(rb); |
| 187 | + cnt++; |
| 188 | + } |
| 189 | + return (int) cnt; |
| 190 | +} |
| 191 | + |
| 192 | +/** |
| 193 | + * @brief Add a byte to ringbuffer |
| 194 | + * @attention use only if you ensurred thread safety otherwise |
| 195 | + * @param[in] rb Ringbuffer to operate on |
| 196 | + * @param[in] c Character to add to ringbuffer |
| 197 | + * @return 0 on success |
| 198 | + * @return -1 if no space available |
| 199 | + */ |
| 200 | +static inline int turb_add_one(tsrb_t *rb, uint8_t c) |
| 201 | +{ |
| 202 | + int retval = -1; |
| 203 | + if (!turb_full(rb)) { |
| 204 | + _turb_push(rb, c); |
| 205 | + retval = 0; |
| 206 | + } |
| 207 | + return retval; |
| 208 | +} |
| 209 | + |
| 210 | +/** |
| 211 | + * @brief Add bytes to ringbuffer |
| 212 | + * @attention use only if you ensurred thread safety otherwise |
| 213 | + * @param[in] rb Ringbuffer to operate on |
| 214 | + * @param[in] src buffer to read from |
| 215 | + * @param[in] n max number of bytes to read from @p src |
| 216 | + * @return nr of bytes read from @p src |
| 217 | + */ |
| 218 | +static inline int turb_add(tsrb_t *rb, const uint8_t *src, size_t n) |
| 219 | +{ |
| 220 | + size_t ret = 0; |
| 221 | + while (n-- && !turb_full(rb)) { |
| 222 | + _turb_push(rb, *src++); |
| 223 | + ret++; |
| 224 | + } |
| 225 | + return (int) ret; |
| 226 | +} |
| 227 | + |
| 228 | +#ifdef __cplusplus |
| 229 | +} |
| 230 | +#endif |
| 231 | + |
| 232 | +/** @} */ |
0 commit comments