agileRTOS (zrtos)  Version 0.8.0 (ghostbuster)
cbuffer.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024 ykat UG (haftungsbeschraenkt) - All Rights Reserved
3  *
4  * Permission for non-commercial use is hereby granted,
5  * free of charge, without warranty of any kind.
6  */
7 #ifndef ZRTOS_CBUFFER_H
8 #define ZRTOS_CBUFFER_H
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 
14 #include <stdarg.h>
15 
16 #include <zrtos/types.h>
17 #include <zrtos/error.h>
18 #include <zrtos/list.h>
19 #include <zrtos/malloc_limit.h>
20 #include <zrtos/assert.h>
21 #include <zrtos/cast.h>
22 
23 
24 #ifndef ZRTOS_CBUFFER__CFG_DATA_LENGTH
25 #define ZRTOS_CBUFFER__CFG_DATA_LENGTH 16
26 #endif
27 
28 #ifndef ZRTOS_CBUFFER__CFG_MALLOC_LIMIT
29 #define ZRTOS_CBUFFER__CFG_MALLOC_LIMIT 200
30 #endif
31 
32 #ifdef ZRTOS_MALLOC__CFG_DISABLE_FREE
33 #error "ZRTOS_MALLOC__CFG_DISABLE_FREE not supported with cbuffer"
34 #endif
35 
37 
38 typedef struct _zrtos_cbuffer_node_t{
44 
45 typedef struct _zrtos_cbuffer_t{
48 
53 
54 /// @todo mutex lock zrtos_cbuffer__malloc_limit
56 
61  ,node
62  );
63  return node;
64 }
65 
70  ,node
71  );
72  return node;
73 }
74 
79  ,node
80  );
81  return node;
82 }
83 
86  ,zrtos_cbuffer_t *ctx
87 ){
89  zrtos_list__push(&ctx->root,&thiz->node);
90  thiz->head = 0;
91  thiz->tail = 0;
92  return true;
93 }
94 
99  &zrtos_cbuffer__malloc_limit
100  ,sizeof(zrtos_cbuffer_node_t)
102  )
103  );
104  if(ret){
105  zrtos_cbuffer_node__init(ret,ctx);
106  }
107  return ret;
108 }
109 
111  zrtos_list__delete(&ctx->root,&thiz->node);
112  zrtos_malloc_limit__free(&zrtos_cbuffer__malloc_limit,thiz);
113 }
114 
116  zrtos_cbuffer_t *thiz
117 ){
118  zrtos_list__init(&thiz->root);
119  return zrtos_cbuffer_node__new(thiz) != 0;
120 }
121 
123  zrtos_list_t *thiz
125 ){
128  node
130  ,node
131  )
133  thiz
135  ,root
136  )
137  );
138 }
139 
141  zrtos_cbuffer_t *thiz
142 ){
144 }
145 
147  zrtos_cbuffer_t *thiz
149 ){
150  txn->thiz = *thiz;
151  txn->head = zrtos_cbuffer__get_last_node(thiz)->head;
152 }
153 
155  zrtos_cbuffer_t *thiz
157 ){
158  zrtos_cbuffer_node_t *next;
160  node->head = txn->head;
161  while((next = zrtos_cbuffer_node__get_next_node(node))){
163  next
164  ,thiz
165  );
166  }
167 }
168 
171 ){
172  return (thiz->head - thiz->tail) & (ZRTOS_CBUFFER__CFG_DATA_LENGTH - 1);
173 }
174 
176  //return zrtos_cbuffer_node__get_length(thiz) == 0;
177  return thiz->head == thiz->tail;
178 }
179 
182 ){
183  return (ZRTOS_CBUFFER__CFG_DATA_LENGTH - 1)
185  ;
186 }
187 
190  ,zrtos_cbuffer_t *ctx
191  ,uint8_t val
192 ){
194 
195  if(zrtos_cbuffer_node__get_free_space(thiz) >= 1){
196  thiz->data[thiz->head++] = val;
197  thiz->head &= (ZRTOS_CBUFFER__CFG_DATA_LENGTH - 1);
198  }else{
200  if(node){
202  node
203  ,ctx
204  ,val
205  );
206  }else{
207  ret = ZRTOS_ERROR__NOMEM;
208  }
209  }
210  return ret;
211 }
212 
215  ,zrtos_cbuffer_t *ctx
216  ,uint8_t *out
217 ){
219  if(!zrtos_cbuffer_node__is_empty(thiz)){
220  *out = thiz->data[thiz->tail++];
221  thiz->tail &= (ZRTOS_CBUFFER__CFG_DATA_LENGTH - 1);
224  zrtos_cbuffer_node__free(thiz,ctx);
225  }
226  }else{
227  ret = ZRTOS_ERROR__AGAIN;
228  }
229  return ret;
230 }
231 
234  ,uint8_t *out
235 ){
237  if(!zrtos_cbuffer_node__is_empty(thiz)){
238  *out = thiz->data[thiz->tail];
239  }else{
240  ret = ZRTOS_ERROR__AGAIN;
241  }
242  return ret;
243 }
244 
246  zrtos_cbuffer_t *thiz
247  ,size_t length
248  ,void (*callback)(void *callback_args,uint8_t ch)
249  ,void *callback_args
250 ){
252  size_t tail;
253  size_t head;
254 
255  while(node && length){
256  head = node->head;
257  tail = node->tail;
258 
259  while(tail != head && length--){
260  callback(callback_args,node->data[tail++]);
261  }
262 
264  }
265 
266  return length == 0 ? ZRTOS_ERROR__SUCCESS : ZRTOS_ERROR__INVAL;
267 }
268 
273  ,node
274  );
275  return zrtos_cbuffer_node__put(node,thiz,val);
276 }
277 
279  zrtos_cbuffer_t *thiz
280  ,size_t len
281  ,size_t *outlen
282  ,...
283 /*
284  ,void *data
285  ,size_t len
286 */
287 ){
289  uint8_t *data;
290  size_t data_len;
291  va_list args;
293 
294  va_start(args,outlen);
295 
297 
298  while(len-- && zrtos_error__is_success(ret)){
299  data = ZRTOS_CAST(uint8_t*,va_arg(args,void*));
300  data_len = va_arg(args,size_t);
301  while(data_len-- && zrtos_error__is_success(ret)){
302  ret = zrtos_cbuffer__put(
303  thiz
304  ,*data++
305  );
306  }
307  }
308 
309  if(zrtos_error__is_error(ret)){
311  }
312 
313  va_end(args);
314 
315  return ret;
316 }
317 
322  ,node
323  );
324  return zrtos_cbuffer_node__peek(node,out);
325 }
326 
331  ,node
332  );
333  return zrtos_cbuffer_node__get(node,thiz,out);
334 }
335 
337  zrtos_cbuffer_t *thiz
338  ,void *data
339  ,size_t len
340  ,size_t *outlen
341 ){
343  uint8_t *tmp = ZRTOS_CAST(uint8_t*,data);
344  while(len--
345  && ZRTOS_ERROR__SUCCESS == (ret = zrtos_cbuffer__get(thiz,tmp++))){
346  ;
347  }
348  *outlen = zrtos_types__ptr_get_byte_distance(tmp,data);
349  return ret;
350 }
351 
353  uint8_t out;
354  return zrtos_cbuffer__get(thiz,&out);
355 }
356 
359  return zrtos_cbuffer_node__is_empty(node);
360 }
361 
364 
365  while(zrtos_list_node__has_next_node(&node->node)){
366  zrtos_cbuffer_node__free(node,thiz);
367  node = zrtos_cbuffer__get_first_node(thiz);
368  }
369 
370  node->head = node->tail = 0;
371 }
372 
374  zrtos_cbuffer_t *thiz
375 ){
376  return zrtos_cbuffer__is_empty(thiz)
379  ;
380 }
381 
383  zrtos_cbuffer_t *thiz
384  ,size_t length
385 ){
387 
388  while(node
389  && length
390  && !zrtos_cbuffer_node__is_empty(node)){
391  length -= ZRTOS_TYPES__MIN(
392  ((size_t)(node->head - node->tail))
393  ,length
394  );
396  }
397 
398  return length == 0;
399 }
400 
402  zrtos_cbuffer_t *thiz
403 ){
405  size_t length = 0;
406 
407  while(node){
408  length += zrtos_cbuffer_node__get_length(node);
410  }
411 
412  return length == 0;
413 }
414 
416  zrtos_cbuffer_t *thiz
417 ){
418  return ZRTOS_ERROR__SUCCESS;
419 }
420 
422  zrtos_cbuffer_t *thiz
423  ,zrtos_cbuffer_t *src
424  ,size_t length
425  ,size_t *outlen
426 ){
428  uint8_t tmp;
429 
430  *outlen = length;
431 
432  while(length){
433  if(zrtos_error__is_success((ret = zrtos_cbuffer__peek(src,&tmp)))
434  && zrtos_error__is_success((ret = zrtos_cbuffer__put(thiz,tmp)))
435  ){
436  length--;
437  zrtos_cbuffer__pop(src);
438  }else{
439  break;
440  }
441  }
442 
443  *outlen -= length;
444 
445  return ret;
446 }
447 
448 #if 0
449 void zrtos_cbuffer_node__debug(
451 ){
452  Serial.println("zrtos_cbuffer_node{");
453  Serial.println("head:");
454  Serial.print(thiz->head);
455  Serial.println("tail:");
456  Serial.print(thiz->tail);
457  Serial.println("data:[");
458 
459  size_t length = 0;
460 
461  for(;length < ZRTOS_CBUFFER__CFG_DATA_LENGTH-1;length++){
462  Serial.print(length);
463  Serial.print(":[");
464  Serial.print(thiz->data[length],HEX);
465  Serial.println("],");
466  }
467 
468  Serial.println("]}");
469 }
470 
471 void zrtos_cbuffer__debug(
472  zrtos_cbuffer_t *thiz
473 ){
475  Serial.print("zrtos_cbuffer{");
476  while(node){
477  zrtos_cbuffer_node__debug(node);
479  }
480  Serial.print("}");
481 }
482 #endif
483 
484 #ifdef __cplusplus
485 }
486 #endif
487 #endif
#define ZRTOS_CAST(type, value)
Definition: cast.h:18
bool zrtos_cbuffer__is_empty(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:357
#define ZRTOS_CBUFFER__CFG_DATA_LENGTH
Definition: cbuffer.h:25
struct _zrtos_cbuffer_t zrtos_cbuffer_t
bool zrtos_cbuffer_node__init(zrtos_cbuffer_node_t *thiz, zrtos_cbuffer_t *ctx)
Definition: cbuffer.h:84
ZRTOS_ASSERT__STATIC_IS_POWER_OF_TWO(ZRTOS_CBUFFER__CFG_DATA_LENGTH)
Try again.
Definition: error.h:35
void zrtos_cbuffer__rollback_write_transaction(zrtos_cbuffer_t *thiz, zrtos_cbuffer_write_transaction_t *txn)
Definition: cbuffer.h:154
void zrtos_list__delete(zrtos_list_t *thiz, zrtos_list_node_t *node)
Definition: list.h:96
zrtos_error_t zrtos_cbuffer__can_read(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:373
zrtos_error_t zrtos_cbuffer__get_ex(zrtos_cbuffer_t *thiz, void *data, size_t len, size_t *outlen)
Definition: cbuffer.h:336
zrtos_list_node_t * zrtos_list__get_last_node(zrtos_list_t *thiz)
Definition: list.h:30
zrtos_error_t zrtos_cbuffer__put(zrtos_cbuffer_t *thiz, uint8_t val)
Definition: cbuffer.h:269
zrtos_cbuffer_node_t * zrtos_cbuffer_node__new(zrtos_cbuffer_t *ctx)
Definition: cbuffer.h:95
bool zrtos_list_node__has_next_node(zrtos_list_node_t *node)
Definition: list.h:45
bool zrtos_list__init(zrtos_list_t *thiz)
Definition: list.h:51
void zrtos_cbuffer__deinit(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:140
void zrtos_malloc_limit__free(zrtos_malloc_limit_t *thiz, void *ptr)
Definition: malloc_limit.h:41
zrtos_error_t zrtos_cbuffer__get(zrtos_cbuffer_t *thiz, uint8_t *out)
Definition: cbuffer.h:327
zrtos_malloc_limit_t zrtos_cbuffer__malloc_limit
Definition: cbuffer.h:55
zrtos_list_node_t * zrtos_list__get_first_node(zrtos_list_t *thiz)
Definition: list.h:26
zrtos_list_node_t * zrtos_list_node__get_next_node(zrtos_list_node_t *node)
Definition: list.h:39
#define zrtos_types__get_container_of(ptr, type, member)
Definition: types.h:69
#define ZRTOS_MALLOC_LIMIT__INIT()
Definition: malloc_limit.h:23
bool zrtos_error__is_error(zrtos_error_t thiz)
Definition: error.h:156
bool zrtos_list_node__init(zrtos_list_node_t *thiz)
Definition: list.h:34
#define ZRTOS_CBUFFER__CFG_MALLOC_LIMIT
Definition: cbuffer.h:29
zrtos_error_t zrtos_cbuffer__pop(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:352
bool zrtos_list__push(zrtos_list_t *thiz, zrtos_list_node_t *node)
Definition: list.h:57
zrtos_cbuffer_node_t * zrtos_cbuffer__get_first_node(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:57
struct _zrtos_cbuffer_node_t zrtos_cbuffer_node_t
void zrtos_cbuffer__start_write_transaction(zrtos_cbuffer_t *thiz, zrtos_cbuffer_write_transaction_t *txn)
Definition: cbuffer.h:146
zrtos_error_t zrtos_cbuffer__peek(zrtos_cbuffer_t *thiz, uint8_t *out)
Definition: cbuffer.h:318
bool zrtos_error__is_success(zrtos_error_t thiz)
Definition: error.h:152
#define ZRTOS_TYPES__MIN(a, b)
Definition: types.h:78
zrtos_error_t zrtos_cbuffer_node__get(zrtos_cbuffer_node_t *thiz, zrtos_cbuffer_t *ctx, uint8_t *out)
Definition: cbuffer.h:213
size_t zrtos_cbuffer__get_length(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:401
size_t zrtos_types__ptr_get_byte_distance(void *bigger, void *smaller)
Definition: types.h:43
Successful program execution status.
Definition: error.h:22
void zrtos_cbuffer__deinit_callback(zrtos_list_t *thiz, zrtos_list_node_t *node)
Definition: cbuffer.h:122
static size_t zrtos_cbuffer_node__get_free_space(zrtos_cbuffer_node_t *thiz)
Definition: cbuffer.h:180
struct _zrtos_cbuffer_write_transaction_t zrtos_cbuffer_write_transaction_t
bool zrtos_cbuffer_node__is_empty(zrtos_cbuffer_node_t *thiz)
Definition: cbuffer.h:175
uint8_t data[ZRTOS_CBUFFER__CFG_DATA_LENGTH]
Definition: cbuffer.h:40
zrtos_list_node_t node
Definition: cbuffer.h:39
Invalid argument.
Definition: error.h:46
Out of memory.
Definition: error.h:36
bool zrtos_cbuffer__can_read_length(zrtos_cbuffer_t *thiz, size_t length)
Definition: cbuffer.h:382
zrtos_cbuffer_node_t * zrtos_cbuffer__get_last_node(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:66
zrtos_error_t zrtos_cbuffer_node__put(zrtos_cbuffer_node_t *thiz, zrtos_cbuffer_t *ctx, uint8_t val)
Definition: cbuffer.h:188
void * zrtos_malloc_limit__malloc(zrtos_malloc_limit_t *thiz, size_t length, size_t limit)
Definition: malloc_limit.h:25
zrtos_cbuffer_node_t * zrtos_cbuffer_node__get_next_node(zrtos_cbuffer_node_t *thiz)
Definition: cbuffer.h:75
zrtos_error_t zrtos_cbuffer__put_ex(zrtos_cbuffer_t *thiz, size_t len, size_t *outlen,...)
Definition: cbuffer.h:278
bool zrtos_cbuffer__init(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:115
void zrtos_cbuffer_node__free(zrtos_cbuffer_node_t *thiz, zrtos_cbuffer_t *ctx)
Definition: cbuffer.h:110
static uint8_t
Definition: mcp2515.h:159
void zrtos_cbuffer__clear(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:362
zrtos_error_t
Definition: error.h:20
zrtos_error_t zrtos_cbuffer__can_write(zrtos_cbuffer_t *thiz)
Definition: cbuffer.h:415
static size_t zrtos_cbuffer_node__get_length(zrtos_cbuffer_node_t *thiz)
Definition: cbuffer.h:169
void zrtos_list__deinit(zrtos_list_t *thiz, void(*callback)(zrtos_list_t *thiz, zrtos_list_node_t *node))
Definition: list.h:115
zrtos_list_t root
Definition: cbuffer.h:46
zrtos_error_t zrtos_cbuffer_node__peek(zrtos_cbuffer_node_t *thiz, uint8_t *out)
Definition: cbuffer.h:232
zrtos_error_t zrtos_cbuffer__pipe(zrtos_cbuffer_t *thiz, zrtos_cbuffer_t *src, size_t length, size_t *outlen)
Definition: cbuffer.h:421
zrtos_error_t zrtos_cbuffer__hash(zrtos_cbuffer_t *thiz, size_t length, void(*callback)(void *callback_args, uint8_t ch), void *callback_args)
Definition: cbuffer.h:245