chunked_ringbuffer.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2021 ML!PA Consulting GmbH
3  *
4  * This file is subject to the terms and conditions of the GNU Lesser
5  * General Public License v2.1. See the file LICENSE in the top level
6  * directory for more details.
7  */
8 
9 #pragma once
10 
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stddef.h>
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
37 #ifndef CONFIG_CHUNK_NUM_MAX
38 #define CONFIG_CHUNK_NUM_MAX (4)
39 #endif
40 
45 typedef struct {
46  uint8_t *buffer;
47  uint8_t *buffer_end;
48  uint8_t *cur;
49  uint8_t *cur_start;
50  uint8_t *protect;
51  uint8_t *chunk_start[CONFIG_CHUNK_NUM_MAX];
52  uint16_t chunk_len[CONFIG_CHUNK_NUM_MAX];
53  uint8_t chunk_cur;
55 
63 typedef void (*crb_foreach_callback_t)(void *ctx, uint8_t *bytes, size_t len);
64 
72 void crb_init(chunk_ringbuf_t *rb, void *buffer, size_t len);
73 
87 unsigned crb_end_chunk(chunk_ringbuf_t *rb, bool valid);
88 
102 static inline bool crb_start_chunk(chunk_ringbuf_t *rb)
103 {
104  /* discard stale chunk */
105  if (rb->cur_start) {
106  crb_end_chunk(rb, false);
107  }
108 
109  /* pointing to the start of the first chunk */
110  if (rb->cur == rb->protect) {
111  return false;
112  }
113 
114  rb->cur_start = rb->cur;
115 
116  if (rb->protect == NULL) {
117  rb->protect = rb->cur_start;
118  }
119 
120  return true;
121 }
122 
137 static inline bool crb_add_byte(chunk_ringbuf_t *rb, uint8_t b)
138 {
139  /* if this is the first chunk, protect will be at start */
140  if (rb->cur == rb->protect &&
141  rb->cur != rb->cur_start) {
142  return false;
143  }
144 
145  *rb->cur = b;
146 
147  /* handle wrap around */
148  if (rb->cur == rb->buffer_end) {
149  rb->cur = rb->buffer;
150  } else {
151  ++rb->cur;
152  }
153 
154  return true;
155 }
156 
172 bool crb_add_bytes(chunk_ringbuf_t *rb, const void *data, size_t len);
173 
190 bool crb_add_chunk(chunk_ringbuf_t *rb, const void *data, size_t len);
191 
201 bool crb_get_chunk_size(chunk_ringbuf_t *rb, size_t *len);
202 
214 bool crb_peek_bytes(chunk_ringbuf_t *rb, void *dst, size_t offset, size_t len);
215 
228 bool crb_consume_chunk(chunk_ringbuf_t *rb, void *dst, size_t len);
229 
244 
245 #ifdef __cplusplus
246 }
247 #endif
248 
bool crb_peek_bytes(chunk_ringbuf_t *rb, void *dst, size_t offset, size_t len)
Get a number of bytes from the first valid chunk without consuming it.
static bool crb_add_byte(chunk_ringbuf_t *rb, uint8_t b)
Insert a byte into the current chunk.
void crb_init(chunk_ringbuf_t *rb, void *buffer, size_t len)
Initialize a Chunked Ringbuffer.
static bool crb_start_chunk(chunk_ringbuf_t *rb)
Start a new chunk on the ringbuffer.
void(* crb_foreach_callback_t)(void *ctx, uint8_t *bytes, size_t len)
Callback function for crb_chunk_foreach.
bool crb_add_bytes(chunk_ringbuf_t *rb, const void *data, size_t len)
Insert a number of bytes into the current chunk.
bool crb_get_chunk_size(chunk_ringbuf_t *rb, size_t *len)
Get the size of the first valid chunk.
bool crb_add_chunk(chunk_ringbuf_t *rb, const void *data, size_t len)
Add a complete chunk to the Ringbuffer.
#define CONFIG_CHUNK_NUM_MAX
The maximum number of chunks that can be stored in a Chunked Ringbuffer.
unsigned crb_end_chunk(chunk_ringbuf_t *rb, bool valid)
Close the current chunk.
bool crb_consume_chunk(chunk_ringbuf_t *rb, void *dst, size_t len)
Remove a chunk from the valid chunk array.
bool crb_chunk_foreach(chunk_ringbuf_t *rb, crb_foreach_callback_t func, void *ctx)
Execute a callback for each byte in the first valid chunk The callback function may be called twice i...
A chunked ringbuffer.
uint8_t chunk_cur
Index of the first valid chunk.
uint8_t * cur_start
start of the currently written chunk
uint8_t * buffer_end
last data element
uint8_t * buffer
pointer to the memory to hold the data
uint8_t * cur
current write pointer
uint8_t * protect
start of the first valid chunk