agileRTOS (zrtos)  Version 0.8.0 (ghostbuster)
str.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_STR_H
8 #define ZRTOS_STR_H
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 
14 #include <stdarg.h>
15 
16 #include <zrtos/types.h>
17 #include <zrtos/cast.h>
18 #include <zrtos/mem.h>
19 
20 
22  char *dest;
23  size_t len;
24  size_t ret;
26 
27 size_t zrtos_str__len(char *str){
28  char *tmp = str+1;
29  while(*str++){}
30  return zrtos_types__ptr_get_byte_distance(str,tmp);
31 }
32 
33 int zrtos_str__cmp(char *a,char *b){
34  size_t a_len = zrtos_str__len(a);
35  size_t b_len = zrtos_str__len(b);
36  int ret = ZRTOS_TYPES__CMP(size_t,a_len,b_len);
37  return ret ? ret : zrtos_mem__cmp(a,b,a_len);
38 }
39 
40 void zrtos_str__reverse(char *str){
42 }
43 
44 /**
45  * @param value
46  * @param str must be str != NULL
47  * @param radix must be radix < 36 && radix >= 1
48  * @return char*
49  */
50 char *zrtos_str__ultoa(uint64_t value, char *str, int radix){
51  char *tp = str;
52  uint64_t i;
53  uint64_t v = value;
54 
55  while(v){
56  i = v % radix;
57  v = v / radix;
58  if(i < 10){
59  *tp++ = i + '0';
60  }else{
61  *tp++ = i + 'a' - 10;
62  }
63  }
64 
66  str
68  );
69 
70  *tp = 0;
71 
72  return tp;
73 }
74 
75 char *zrtos_str__ltoa(int64_t value, char *str, int radix){
76  if(value < 0){
77  value = -value;
78  *str++ = '-';
79  }
80  return zrtos_str__ultoa(value,str,radix);
81 }
82 
83 #define ZRTOS_STR__CFG_DTOA_PRECISION 1000000
84 
85 char *zrtos_str__dtoa(double val,char *str){
86  int64_t c = (val * ZRTOS_STR__CFG_DTOA_PRECISION) + .5;
87  int64_t d = c / ZRTOS_STR__CFG_DTOA_PRECISION;
88  uint64_t f = c - (d * ZRTOS_STR__CFG_DTOA_PRECISION);
89 
90  str = zrtos_str__ltoa(d,str,10);
91  *str++ = '.';
92  return zrtos_str__ultoa(f,str,10);
93 }
94 
96  void (*putc)(void *args,char c)
97  ,void *putc_args
98  ,char const *fmt
99  ,va_list arg
100 ){
101  char ch;
102  uint8_t out_mod;
103  char *out_str;
104  size_t out_len;
105  uint64_t out_num;
106  uint8_t out_radix;
107  char buffer[64];
108 
109  while((ch = *fmt++)){
110  out_mod = 0x1;
111  if(ch == '%'){
112  switch((ch = *fmt++)){
113  case 'c':
114  out_mod = 0x1;
115  ch = va_arg(arg,int);
116  break;
117  case 's':
118  out_mod = 0x4 | 0x2;
119  out_str = va_arg(arg,char*);
120  break;
121  case 'S':
122  out_mod = 0x4;
123  out_len = va_arg(arg,size_t);
124  out_str = va_arg(arg,char*);
125  break;
126  case 'd':{
127  int tmp = va_arg(arg, int);
128  out_num = (uint64_t)tmp;
129  out_mod = 0x8 | 0x4 | 0x2;
130  out_radix = 10;
131  if(tmp < 0){
132  ch = '-';
133  out_mod |= 0x1;
134  }
135  }
136  break;
137  case 'u':{
138  out_num = (uint64_t)va_arg(arg, int);
139  out_mod = 0x8 | 0x4 | 0x2;
140  out_radix = 10;
141  }
142  break;
143  case 'f':{
144  double out_double = va_arg(arg, double);
145  zrtos_str__dtoa(out_double,buffer);
146  out_mod = 0x4 | 0x2;
147  out_str = buffer;
148  }
149  break;
150  case 'p':
151  out_num = (uint64_t)va_arg(arg,uintptr_t);
152  goto L_PRINT_HEX;
153  case 'x':
154  out_num = va_arg(arg,uint64_t);
155 L_PRINT_HEX:
156  out_mod = 0x8 | 0x4 | 0x2;
157  out_radix = 16;
158  break;
159  case 0:
160  return;
161  }
162  }
163 
164  if(out_mod & 0x1){
165  putc(putc_args,ch);
166  }
167  if(out_mod & 0x8){
168  zrtos_str__ultoa(out_num, buffer, out_radix);
169  out_str = buffer;
170  }
171  if(out_mod & 0x2){
172  out_len = zrtos_str__len(out_str);
173  }
174  if(out_mod & 0x4){
175  while(out_len--){
176  putc(putc_args,*out_str++);
177  }
178  }
179  }
180 }
181 
182 static void zrtos_str__vsnprintf_cb(void *args_,char ch){
184  if(args->len--){
185  *args->dest++ = ch;
186  }
187  args->ret++;
188 }
189 
190 int zrtos_str__vsnprintf(char *dest,size_t len,char const *fmt, ...){
191  va_list arg;
193  .dest = dest
194  ,.len = len
195  };
196  va_start(arg, fmt);
199  ,&args
200  ,fmt
201  ,arg
202  );
203  va_end(arg);
204  return args.ret;
205 }
206 
207 size_t zrtos_str__spn(const char *s1, const char *s2){
208  register const char *p = s1, *spanp;
209  register char c, sc;
210 
211  /*
212  * Skip any characters in s2, excluding the terminating \0.
213  */
214 cont:
215  c = *p++;
216  for (spanp = s2; (sc = *spanp++) != 0;){
217  if (sc == c){
218  goto cont;
219  }
220  }
221  return (p - 1 - s1);
222 }
223 
224 size_t zrtos_str__cspn(const char *s1,const char *s2){
225  register const char *p, *spanp;
226  register char c, sc;
227 
228  /*
229  * Stop as soon as we find any character from s2. Note that there
230  * must be a NUL in s2; it suffices to stop when we find that, too.
231  */
232  for (p = s1;;) {
233  c = *p++;
234  spanp = s2;
235  do {
236  if ((sc = *spanp++) == c){
237  return (p - 1 - s1);
238  }
239  } while (sc != 0);
240  }
241  /* NOTREACHED */
242 }
243 
244 /* Parse S into tokens separated by characters in DELIM.
245  If S is NULL, the saved pointer in SAVE_PTR is used as
246  the next starting point. For example:
247  char s[] = "-abc-=-def";
248  char *sp;
249  x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def"
250  x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL
251  x = strtok_r(NULL, "=", &sp); // x = NULL
252  // s = "abc\0-def\0"
253 */
254 char *zrtos_str__tok_r(char *s, const char *delim, char **save_ptr){
255  char *end;
256  if (s == NULL)
257  s = *save_ptr;
258  if (*s == '\0')
259  {
260  *save_ptr = s;
261  return NULL;
262  }
263  /* Scan leading delimiters. */
264  s += zrtos_str__spn(s, delim);
265  if (*s == '\0')
266  {
267  *save_ptr = s;
268  return NULL;
269  }
270  /* Find the end of the token. */
271  end = s + zrtos_str__cspn(s, delim);
272  if (*end == '\0')
273  {
274  *save_ptr = end;
275  return s;
276  }
277  /* Terminate the token and make *SAVE_PTR point past it. */
278  *end = '\0';
279  *save_ptr = end + 1;
280  return s;
281 }
282 
283 size_t zrtos_str__to_hex(char *dest,void *src,size_t len){
284  uint8_t *tmp = ZRTOS_CAST(uint8_t*,src);
285  while(len--){
286  uint8_t c = *tmp++;
287  uint8_t l = (c & 0xF) + '0';
288  uint8_t h = (c >> 4) + '0';
289 
290  if(h > '9'){
291  h += 'A' - '9';
292  }
293  if(l > '9'){
294  l += 'A' - '9';
295  }
296 
297  *dest++ = h;
298  *dest++ = l;
299  }
300  return zrtos_types__ptr_get_byte_distance(tmp,src)*2;
301 }
302 
303 
304 #ifdef __cplusplus
305 }
306 #endif
307 #endif
#define ZRTOS_CAST(type, value)
Definition: cast.h:18
char * zrtos_str__dtoa(double val, char *str)
Definition: str.h:85
size_t zrtos_str__spn(const char *s1, const char *s2)
Definition: str.h:207
size_t zrtos_str__len(char *str)
Definition: str.h:27
#define ZRTOS_TYPES__CMP(type, a_len, b_len)
Definition: types.h:80
char * zrtos_str__ltoa(int64_t value, char *str, int radix)
Definition: str.h:75
char * zrtos_str__ultoa(uint64_t value, char *str, int radix)
Definition: str.h:50
void zrtos_mem__reverse(void *dest, size_t len)
Definition: mem.h:126
size_t zrtos_str__to_hex(char *dest, void *src, size_t len)
Definition: str.h:283
struct _zrtos_str__vsnprintf_cb_args_t zrtos_str__vsnprintf_cb_args_t
size_t zrtos_str__cspn(const char *s1, const char *s2)
Definition: str.h:224
size_t zrtos_types__ptr_get_byte_distance(void *bigger, void *smaller)
Definition: types.h:43
#define ZRTOS_STR__CFG_DTOA_PRECISION
Definition: str.h:83
int zrtos_str__cmp(char *a, char *b)
Definition: str.h:33
static void zrtos_str__vsnprintf_cb(void *args_, char ch)
Definition: str.h:182
char * zrtos_str__tok_r(char *s, const char *delim, char **save_ptr)
Definition: str.h:254
void zrtos_str__reverse(char *str)
Definition: str.h:40
int zrtos_mem__cmp(void *str1, void *str2, size_t count)
Definition: mem.h:113
static uint8_t
Definition: mcp2515.h:159
int zrtos_str__vsnprintf(char *dest, size_t len, char const *fmt,...)
Definition: str.h:190
static void zrtos_str__vsnprintf_internal(void(*putc)(void *args, char c), void *putc_args, char const *fmt, va_list arg)
Definition: str.h:95