ASCII Serial Com
Serial communication library between computers, microcontrollers, FPGAs, etc. Uses only ASCII. Not the most efficient protocol, but meant to be easy to read
Loading...
Searching...
No Matches
circular_buffer.h
Go to the documentation of this file.
1#ifndef CIRCULAR_BUFFER_H
2#define CIRCULAR_BUFFER_H
3
4/** \file */
5
6#include <inttypes.h>
7#include <stdbool.h>
8#include <stddef.h>
9#include <stdint.h>
10#ifdef linux
11#include <stdio.h>
12#endif
13
14/** \brief circular buffer struct
15 *
16 * Keeps track of the state of the circular buffer
17 * Use this for a buffer of unit8's.
18 *
19 */
21 size_t capacity; /**< capacity of actual data buffer */
22 size_t size; /**< N elements in circ buffer */
23 size_t iStart; /**< front element of buffer */
24 size_t iStop; /**< 1 past the back element of buffer */
25 uint8_t *buffer; /**< pointer to actual data buffer */
27
28/** \brief circular buffer init method
29 *
30 * Initialize circular buffer
31 * THE BUFFER MUST BE SMALLER THAN (< not <=) SIZE_T ON THE PLATFORM
32 * Use this for a buffer of unit8's.
33 *
34 * May throw an \ref asc_exception
35 *
36 * \param circ_buf is a pointer to an uninitialized circular buffer struct
37 *
38 * \param capacity is the length of buffer (uint8_t array). **It must be a
39 * power of 2!** If it's not, a \ref asc_exception ASC_ERROR_CB_BAD_CAPACITY
40 * will be raised.
41 *
42 * \param buffer is a pointer to the buffer (uint8_t array), which must be
43 * pre-allocated
44 *
45 */
47 const size_t capacity, uint8_t *buffer);
48
49/** \brief circular buffer get number of elements
50 *
51 * circular buffer get number of elements
52 * Use this for a buffer of unit8's.
53 *
54 * \param circ_buf is a pointer to an initialized circular buffer struct
55 * \return the number of elements in the buffer
56 *
57 */
59
60/** \brief circular buffer get if full
61 *
62 * Use this for a buffer of unit8's.
63 *
64 * \param circ_buf is a pointer to an initialized circular buffer struct
65 * \return true true if the buffer is full
66 *
67 */
69
70/** \brief circular buffer get if empty
71 *
72 * Use this for a buffer of unit8's.
73 *
74 * \param circ_buf is a pointer to an initialized circular buffer struct
75 * \return true if the buffer is empty
76 *
77 */
79
80/** \brief circular buffer print contents
81 *
82 * Use this for debugging
83 *
84 * outfile is usually stderr or stdout
85 *
86 * verbosity is from 0 to 4 with greater increasing verbosity
87 *
88 */
89#ifdef linux
91 FILE *outfile, uint8_t verbosity);
92#endif
93
94/** \brief circular buffer get element
95 *
96 * Use this for a buffer of unit8's.
97 *
98 * \param circ_buf is a pointer to an initialized circular buffer struct
99 * \param iElement indexes the circular buffer. The element will be iElements
100 * back from the front of the circular buffer \return the entry at iElement
101 *
102 * May throw an \ref asc_exception
103 *
104 */
106 const size_t iElement);
107
108/** \brief circular buffer push front
109 *
110 * Pushes the given element onto the front of the buffer, making it the new
111 * front element. Use this for a buffer of unit8's.
112 *
113 * \param circ_buf is a pointer to an initialized circular buffer struct
114 * \param element the element to be pushed onto the front of the buffer
115 *
116 */
118 const uint8_t element);
119
120/** \brief circular buffer push back
121 *
122 * Pushes the given element onto the back of the buffer, making it the new back
123 * element. Use this for a buffer of unit8's.
124 *
125 * \param circ_buf is a pointer to an initialized circular buffer struct
126 * \param element the element to be pushed onto the back of the buffer
127 *
128 */
130 const uint8_t element);
131
132/** \brief circular buffer pop front
133 *
134 * Pops an element off of the front of the buffer, both removing it and
135 * returning it. User's responsibility to first check if the buffer is empty.
136 * Use this for a buffer of unit8's.
137 *
138 * \param circ_buf is a pointer to an initialized circular buffer struct
139 * \return element the element popped off the front of the buffer
140 *
141 */
143
144/** \brief circular buffer pop back
145 *
146 * Pops an element off of the back of the buffer, both removing it and
147 * returning it. User's responsibility to first check if the buffer is empty.
148 * Use this for a buffer of unit8's.
149 *
150 * \param circ_buf is a pointer to an initialized circular buffer struct
151 * \return the element to be popped off the back of the buffer
152 *
153 */
155
156/** \brief circular buffer remove elements from front until you find the given
157 * value
158 *
159 * Remove elements from the front of the buffer until the given value is found.
160 * If the value isn't in the buffer, will empty the buffer.
161 *
162 * \param circ_buf is a pointer to an initialized circular buffer struct
163 * \param value is the value you want to remove the front of the buffer up to.
164 * \param inclusive: if true, then remove the given value, otherwise all before
165 * the given value
166 *
167 */
169 const uint8_t value,
170 const bool inclusive);
171
172/** \brief circular buffer remove elements from back until you find the given
173 * value
174 *
175 * Remove elements from the back of the buffer until the given value is found.
176 * If the value isn't in the buffer, will empty the buffer.
177 *
178 * \param circ_buf is a pointer to an initialized circular buffer struct
179 * \param value is the value you want to remove the back of the buffer up to.
180 * \param inclusive: if true, then remove the given value, otherwise all after
181 * the given value
182 *
183 */
185 const uint8_t value,
186 const bool inclusive);
187
188/** \brief circular buffer find index of first occurance of value
189 *
190 * Finds the index of the first element with value equal to the given value.
191 * If the value is not found in the buffer, the return value will be >= the
192 * size of the buffer.
193 *
194 * \param circ_buf is a pointer to an initialized circular buffer struct
195 * \param value is the value you want to find
196 * \return the index where the value can be found using
197 * circular_buffer_get_element_uint8, will be >= size if not found
198 * \sa circular_buffer_get_element_uint8
199 *
200 */
202 const uint8_t value);
203
204/** \brief circular buffer find index of last occurance of value
205 *
206 * Finds the index of the last element with value equal to the given value.
207 * If the value is not found in the buffer, the return value will be >= the
208 * size of the buffer.
209 *
210 * \param circ_buf is a pointer to an initialized circular buffer struct
211 * \param value is the value you want to find
212 * \return the index where the value can be found using
213 * circular_buffer_get_element_uint8, will be >= size if not found
214 * \sa circular_buffer_get_element_uint8
215 *
216 */
218 const uint8_t value);
219
220/** \brief circular buffer count the number of a given value
221 *
222 * Counts the number of elements in the buffer that match the given value
223 *
224 * \param circ_buf is a pointer to an initialized circular buffer struct
225 * \param value is the value you want to find
226 * \return the number of matches found
227 *
228 */
230 const uint8_t value);
231
232/** \brief circular buffer get first block
233 *
234 * Internally, the data may wrap around the end of the block of memory. This
235 * function gives you access to the memory block up to the end of the memory
236 * block, or if the data doesn't wrap, up to the end of the data.
237 *
238 * This can be used followed by circular_buffer_delete_first_block_uint8 to
239 * "pop_front" a whole block of data at once.
240 *
241 * \sa circular_buffer_delete_first_block_uint8
242 *
243 * \param circ_buf is a pointer to an initialized circular buffer struct
244 * \param outBlock is a pointer to the start of the block of memory
245 * \return size of the block pointed to by outBlock
246 *
247 */
248size_t
250 const uint8_t **outBlock);
251
252/** \brief circular buffer delete first block
253 *
254 * Internally, the data may wrap around the end of the block of memory. This
255 * function deletes the memory block from the current start of the circular
256 * buffer up to the end of the memory block, or if the data doesn't wrap, up to
257 * the end of the data.
258 *
259 * This can be used after circular_buffer_get_first_block_uint8 to "pop_front"
260 * a whole block of data at once.
261 *
262 * \sa circular_buffer_get_first_block_uint8
263 *
264 * \param circ_buf is a pointer to an initialized circular buffer struct
265 * \return size of the block deleted
266 *
267 */
268size_t
270
271/** \brief circular buffer push a block of memory on back
272 *
273 * Pushes a block of memory onto back
274 *
275 * Will wrap around and overrite front if buffer gets full
276 *
277 * \param circ_buf is a pointer to an initialized circular buffer struct
278 *
279 * \param source is the start of the source memory block
280 *
281 * \param source_size is the size of the source memory block
282 *
283 */
285 const uint8_t *source,
286 size_t source_size);
287
288/** \brief circular buffer pop from front into a block of memory
289 *
290 * Pops elements from front into a block of memory
291 *
292 * Won't pop all elements if circular buffer wraps around it's internal
293 * memory or there isn't enough source size
294 *
295 * \param circ_buf is a pointer to an initialized circular buffer struct
296 *
297 * \param destination is the start of the destination memory block
298 *
299 * \param source_size is the size of the destination memory block
300 *
301 * \return total number of elements popped from buffer (and written to block)
302 *
303 */
305 uint8_t *destination,
306 size_t dest_size);
307
308/** \brief circular buffer push back reading from file descriptor
309 *
310 * Calls POSIX read once into the circular buffer
311 *
312 * Doesn't overwrite the front of the buffer like the normal push_back
313 * does. Stops when full.
314 *
315 * Won't necessarily fill up the buffer, even if there are bytes to read
316 *
317 * \param circ_buf is a pointer to an initialized circular buffer struct
318 *
319 * \return total number of elements pushed onto buffer (and read from file)
320 *
321 */
322#ifdef linux
324 const int fd);
325
326/** \brief circular buffer pop front writing to file descriptor
327 *
328 * Calls POSIX write once from the circular buffer
329 *
330 * Won't necessarily empty the buffer, even if the file is available for
331 * writing
332 *
333 * \param circ_buf is a pointer to an initialized circular buffer struct
334 *
335 * \return total number of elements popped from buffer (and written to file)
336 *
337 */
339 const int fd);
340#endif
341
342/** \brief circular buffer clear
343 *
344 * Resets the circular buffer to empty and starting from the beginning of the
345 * memory buffer
346 *
347 * \param circ_buf is a pointer to an initialized circular buffer struct
348 *
349 */
351
352/** \brief circular buffer push back string (null terminated)
353 *
354 * Pushes null terminated string onto buffer (without pushing the null)
355 *
356 * For testing, NOT RECOMMENDED FOR MICROCONTROLLER USE
357 *
358 * \param circ_buf is a pointer to an initialized circular buffer struct
359 *
360 * \param string: null terminated string like a string literal
361 *
362 * \return total number of elements pushed onto buffer
363 *
364 */
366 const char *string);
367
368/** \brief circular buffer remove unfinished frames from front of buffer
369 *
370 * Removes from the front of the buffer any frames that haven't ended before
371 * an ended frame. If the buffer just contains an unfinished frame (e.g. that
372 * hasn't finished reading in yet), that isn't removed.
373 *
374 * More concretely: The first endChar is found. Any elements before the
375 * startChar preceding endChar are removed. If the endChar isn't found, any
376 * elements before the last startChar are removed. If no startChar is found
377 * either, the buffer is cleared.
378 *
379 * Additionally, if endChar is front or there is no startChar before the first
380 * endChar, everything up to and including endChar is deleted and the function
381 * is recursed.
382 *
383 * \param circ_buf is a pointer to an initialized circular buffer struct
384 *
385 * \param startChar designates the start of frames
386 *
387 * \param endChar designates the end of frames
388 *
389 * \return the number of elements removed
390 *
391 */
393 circular_buffer_uint8 *circ_buf, const char startChar, const char endChar);
394
395/** \brief circular buffer access raw blocks of data for a given range of
396 * elements
397 *
398 * Given a start element iStart, and a number of elements to access nElem,
399 * gives access to the raw memory block(s) that contain the elements. This
400 * may be a single block of memory or two, since the elements may wrap
401 * around the end of the underlying memory.
402 *
403 * Example use:
404 *
405 * uint8_t* blocks[2];
406 * size_t blocks_sizes[2];
407 *
408 * size_t nBlocks = circular_buffer_get_blocks_uint8(cb, 3, 5, blocks,
409 * blocks_sizes);
410 *
411 * for(size_t iBlock=0; iBlock < nBlocks; iBlock++) {
412 * for(size_t iElem=0; iElem < blocks_sizes[iBlock]; iElem++) {
413 * uint8_t elem = blocks[iBlock][iElem];
414 * }
415 * }
416 *
417 * \param circ_buf is a pointer to an initialized circular buffer struct
418 *
419 * \param iStart the first element of the block requested
420 *
421 * \param nElem the size of the block requested
422 *
423 * \param blocks output array of pointers to blocks. User should allocate
424 * uint8_t* blocks[2];
425 *
426 * \param blocks_sizes output array of size of blocks. User should allocate
427 * size_t blocks_sizes[2];
428 *
429 * \return the number of memory blocks
430 *
431 * Throws ASC_ERROR_CB_OOB if iStart + nElem is > size of buffer
432 *
433 */
435 size_t iStart, size_t nElem,
436 uint8_t **blocks, size_t *blocks_sizes);
437
438#endif
size_t circular_buffer_pop_front_to_fd_uint8(circular_buffer_uint8 *circ_buf, const int fd)
circular buffer pop front writing to file descriptor
uint8_t circular_buffer_pop_back_uint8(circular_buffer_uint8 *circ_buf)
circular buffer pop back
void circular_buffer_remove_front_to_uint8(circular_buffer_uint8 *circ_buf, const uint8_t value, const bool inclusive)
circular buffer remove elements from front until you find the given value
size_t circular_buffer_count_uint8(const circular_buffer_uint8 *circ_buf, const uint8_t value)
circular buffer count the number of a given value
size_t circular_buffer_get_size_uint8(const circular_buffer_uint8 *circ_buf)
circular buffer get number of elements
size_t circular_buffer_pop_front_block_uint8(circular_buffer_uint8 *circ_buf, uint8_t *destination, size_t dest_size)
circular buffer pop from front into a block of memory
void circular_buffer_init_uint8(circular_buffer_uint8 *circ_buf, const size_t capacity, uint8_t *buffer)
circular buffer init method
size_t circular_buffer_remove_front_unfinished_frames_uint8(circular_buffer_uint8 *circ_buf, const char startChar, const char endChar)
circular buffer remove unfinished frames from front of buffer
size_t circular_buffer_get_blocks_uint8(circular_buffer_uint8 *circ_buf, size_t iStart, size_t nElem, uint8_t **blocks, size_t *blocks_sizes)
circular buffer access raw blocks of data for a given range of elements
uint8_t circular_buffer_get_element_uint8(const circular_buffer_uint8 *circ_buf, const size_t iElement)
circular buffer get element
size_t circular_buffer_find_first_uint8(const circular_buffer_uint8 *circ_buf, const uint8_t value)
circular buffer find index of first occurance of value
uint8_t circular_buffer_pop_front_uint8(circular_buffer_uint8 *circ_buf)
circular buffer pop front
bool circular_buffer_is_full_uint8(const circular_buffer_uint8 *circ_buf)
circular buffer get if full
size_t circular_buffer_get_first_block_uint8(const circular_buffer_uint8 *circ_buf, const uint8_t **outBlock)
circular buffer get first block
void circular_buffer_remove_back_to_uint8(circular_buffer_uint8 *circ_buf, const uint8_t value, const bool inclusive)
circular buffer remove elements from back until you find the given value
size_t circular_buffer_delete_first_block_uint8(circular_buffer_uint8 *circ_buf)
circular buffer delete first block
size_t circular_buffer_push_back_from_fd_uint8(circular_buffer_uint8 *circ_buf, const int fd)
circular buffer push back reading from file descriptor
size_t circular_buffer_push_back_string_uint8(circular_buffer_uint8 *circ_buf, const char *string)
circular buffer push back string (null terminated)
void circular_buffer_clear_uint8(circular_buffer_uint8 *circ_buf)
circular buffer clear
size_t circular_buffer_find_last_uint8(const circular_buffer_uint8 *circ_buf, const uint8_t value)
circular buffer find index of last occurance of value
bool circular_buffer_is_empty_uint8(const circular_buffer_uint8 *circ_buf)
circular buffer get if empty
void circular_buffer_push_front_uint8(circular_buffer_uint8 *circ_buf, const uint8_t element)
circular buffer push front
void circular_buffer_push_back_block_uint8(circular_buffer_uint8 *circ_buf, const uint8_t *source, size_t source_size)
circular buffer push a block of memory on back
void circular_buffer_push_back_uint8(circular_buffer_uint8 *circ_buf, const uint8_t element)
circular buffer push back
struct circular_buffer_uint8_struct circular_buffer_uint8
circular buffer struct
void circular_buffer_print_uint8(const circular_buffer_uint8 *circ_buf, FILE *outfile, uint8_t verbosity)
circular buffer print contents
circular buffer struct