1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_SYS_CBPRINTF_CXX_H_
8 #define ZEPHYR_INCLUDE_SYS_CBPRINTF_CXX_H_
9 #ifdef __cplusplus
10 
11 /* C++ version for detecting a pointer to a string. */
z_cbprintf_cxx_is_pchar(char *,bool const_as_fixed)12 static inline int z_cbprintf_cxx_is_pchar(char *, bool const_as_fixed)
13 {
14 	ARG_UNUSED(const_as_fixed);
15 	return 1;
16 }
17 
z_cbprintf_cxx_is_pchar(const char *,bool const_as_fixed)18 static inline int z_cbprintf_cxx_is_pchar(const char *, bool const_as_fixed)
19 {
20 	return const_as_fixed ? 0 : 1;
21 }
22 
z_cbprintf_cxx_is_pchar(volatile char *,bool const_as_fixed)23 static inline int z_cbprintf_cxx_is_pchar(volatile char *, bool const_as_fixed)
24 {
25 	ARG_UNUSED(const_as_fixed);
26 	return 1;
27 }
28 
z_cbprintf_cxx_is_pchar(const volatile char *,bool const_as_fixed)29 static inline int z_cbprintf_cxx_is_pchar(const volatile char *, bool const_as_fixed)
30 {
31 	ARG_UNUSED(const_as_fixed);
32 	return 1;
33 }
34 
z_cbprintf_cxx_is_pchar(unsigned char *,bool const_as_fixed)35 static inline int z_cbprintf_cxx_is_pchar(unsigned char *, bool const_as_fixed)
36 {
37 	ARG_UNUSED(const_as_fixed);
38 	return 1;
39 }
40 
z_cbprintf_cxx_is_pchar(const unsigned char *,bool const_as_fixed)41 static inline int z_cbprintf_cxx_is_pchar(const unsigned char *, bool const_as_fixed)
42 {
43 	return const_as_fixed ? 0 : 1;
44 }
45 
z_cbprintf_cxx_is_pchar(volatile unsigned char *,bool const_as_fixed)46 static inline int z_cbprintf_cxx_is_pchar(volatile unsigned char *, bool const_as_fixed)
47 {
48 	ARG_UNUSED(const_as_fixed);
49 	return 1;
50 }
51 
z_cbprintf_cxx_is_pchar(const volatile unsigned char *,bool const_as_fixed)52 static inline int z_cbprintf_cxx_is_pchar(const volatile unsigned char *, bool const_as_fixed)
53 {
54 	ARG_UNUSED(const_as_fixed);
55 	return 1;
56 }
z_cbprintf_cxx_is_pchar(wchar_t *,bool const_as_fixed)57 static inline int z_cbprintf_cxx_is_pchar(wchar_t *, bool const_as_fixed)
58 {
59 	ARG_UNUSED(const_as_fixed);
60 	return 1;
61 }
62 
z_cbprintf_cxx_is_pchar(const wchar_t *,bool const_as_fixed)63 static inline int z_cbprintf_cxx_is_pchar(const wchar_t *, bool const_as_fixed)
64 {
65 	return const_as_fixed ? 0 : 1;
66 }
67 
z_cbprintf_cxx_is_pchar(volatile wchar_t *,bool const_as_fixed)68 static inline int z_cbprintf_cxx_is_pchar(volatile wchar_t *, bool const_as_fixed)
69 {
70 	ARG_UNUSED(const_as_fixed);
71 	return 1;
72 }
73 
z_cbprintf_cxx_is_pchar(const volatile wchar_t *,bool const_as_fixed)74 static inline int z_cbprintf_cxx_is_pchar(const volatile wchar_t *, bool const_as_fixed)
75 {
76 	ARG_UNUSED(const_as_fixed);
77 	return 1;
78 }
79 
80 template < typename T >
z_cbprintf_cxx_is_pchar(T arg,bool const_as_fixed)81 static inline int z_cbprintf_cxx_is_pchar(T arg, bool const_as_fixed)
82 {
83 	ARG_UNUSED(arg);
84 	_Pragma("GCC diagnostic push")
85 	_Pragma("GCC diagnostic ignored \"-Wpointer-arith\"")
86 	ARG_UNUSED(const_as_fixed);
87 	return 0;
88 	_Pragma("GCC diagnostic pop")
89 }
90 
91 /* C++ version for determining if variable type is numeric and fits in 32 bit word. */
z_cbprintf_cxx_is_word_num(char)92 static inline int z_cbprintf_cxx_is_word_num(char)
93 {
94 	return 1;
95 }
96 
z_cbprintf_cxx_is_word_num(unsigned char)97 static inline int z_cbprintf_cxx_is_word_num(unsigned char)
98 {
99 	return 1;
100 }
101 
z_cbprintf_cxx_is_word_num(short)102 static inline int z_cbprintf_cxx_is_word_num(short)
103 {
104 	return 1;
105 }
106 
z_cbprintf_cxx_is_word_num(unsigned short)107 static inline int z_cbprintf_cxx_is_word_num(unsigned short)
108 {
109 	return 1;
110 }
111 
z_cbprintf_cxx_is_word_num(int)112 static inline int z_cbprintf_cxx_is_word_num(int)
113 {
114 	return 1;
115 }
116 
z_cbprintf_cxx_is_word_num(unsigned int)117 static inline int z_cbprintf_cxx_is_word_num(unsigned int)
118 {
119 	return 1;
120 }
121 
z_cbprintf_cxx_is_word_num(long)122 static inline int z_cbprintf_cxx_is_word_num(long)
123 {
124 	return (sizeof(long) <= sizeof(uint32_t)) ? 1 : 0;
125 }
126 
z_cbprintf_cxx_is_word_num(unsigned long)127 static inline int z_cbprintf_cxx_is_word_num(unsigned long)
128 {
129 	return (sizeof(long) <= sizeof(uint32_t)) ? 1 : 0;
130 }
131 
132 template < typename T >
z_cbprintf_cxx_is_word_num(T arg)133 static inline int z_cbprintf_cxx_is_word_num(T arg)
134 {
135 	ARG_UNUSED(arg);
136 	_Pragma("GCC diagnostic push")
137 	_Pragma("GCC diagnostic ignored \"-Wpointer-arith\"")
138 	return 0;
139 	_Pragma("GCC diagnostic pop")
140 }
141 
142 /* C++ version for determining if argument is a none character pointer. */
z_cbprintf_cxx_is_none_char_ptr(char)143 static inline int z_cbprintf_cxx_is_none_char_ptr(char)
144 {
145 	return 0;
146 }
147 
z_cbprintf_cxx_is_none_char_ptr(unsigned char)148 static inline int z_cbprintf_cxx_is_none_char_ptr(unsigned char)
149 {
150 	return 0;
151 }
152 
z_cbprintf_cxx_is_none_char_ptr(short)153 static inline int z_cbprintf_cxx_is_none_char_ptr(short)
154 {
155 	return 0;
156 }
157 
z_cbprintf_cxx_is_none_char_ptr(unsigned short)158 static inline int z_cbprintf_cxx_is_none_char_ptr(unsigned short)
159 {
160 	return 0;
161 }
162 
z_cbprintf_cxx_is_none_char_ptr(int)163 static inline int z_cbprintf_cxx_is_none_char_ptr(int)
164 {
165 	return 0;
166 }
167 
z_cbprintf_cxx_is_none_char_ptr(unsigned int)168 static inline int z_cbprintf_cxx_is_none_char_ptr(unsigned int)
169 {
170 	return 0;
171 }
172 
z_cbprintf_cxx_is_none_char_ptr(long)173 static inline int z_cbprintf_cxx_is_none_char_ptr(long)
174 {
175 	return 0;
176 }
177 
z_cbprintf_cxx_is_none_char_ptr(unsigned long)178 static inline int z_cbprintf_cxx_is_none_char_ptr(unsigned long)
179 {
180 	return 0;
181 }
182 
z_cbprintf_cxx_is_none_char_ptr(long long)183 static inline int z_cbprintf_cxx_is_none_char_ptr(long long)
184 {
185 	return 0;
186 }
187 
z_cbprintf_cxx_is_none_char_ptr(unsigned long long)188 static inline int z_cbprintf_cxx_is_none_char_ptr(unsigned long long)
189 {
190 	return 0;
191 }
192 
z_cbprintf_cxx_is_none_char_ptr(float)193 static inline int z_cbprintf_cxx_is_none_char_ptr(float)
194 {
195 	return 0;
196 }
197 
z_cbprintf_cxx_is_none_char_ptr(double)198 static inline int z_cbprintf_cxx_is_none_char_ptr(double)
199 {
200 	return 0;
201 }
202 
z_cbprintf_cxx_is_none_char_ptr(char *)203 static inline int z_cbprintf_cxx_is_none_char_ptr(char *)
204 {
205 	return 0;
206 }
207 
z_cbprintf_cxx_is_none_char_ptr(volatile char *)208 static inline int z_cbprintf_cxx_is_none_char_ptr(volatile char *)
209 {
210 	return 0;
211 }
212 
z_cbprintf_cxx_is_none_char_ptr(const char *)213 static inline int z_cbprintf_cxx_is_none_char_ptr(const char *)
214 {
215 	return 0;
216 }
217 
z_cbprintf_cxx_is_none_char_ptr(const volatile char *)218 static inline int z_cbprintf_cxx_is_none_char_ptr(const volatile char *)
219 {
220 	return 0;
221 }
222 
z_cbprintf_cxx_is_none_char_ptr(unsigned char *)223 static inline int z_cbprintf_cxx_is_none_char_ptr(unsigned char *)
224 {
225 	return 0;
226 }
227 
z_cbprintf_cxx_is_none_char_ptr(volatile unsigned char *)228 static inline int z_cbprintf_cxx_is_none_char_ptr(volatile unsigned char *)
229 {
230 	return 0;
231 }
232 
z_cbprintf_cxx_is_none_char_ptr(const unsigned char *)233 static inline int z_cbprintf_cxx_is_none_char_ptr(const unsigned char *)
234 {
235 	return 0;
236 }
237 
z_cbprintf_cxx_is_none_char_ptr(const volatile unsigned char *)238 static inline int z_cbprintf_cxx_is_none_char_ptr(const volatile unsigned char *)
239 {
240 	return 0;
241 }
242 
243 template < typename T >
z_cbprintf_cxx_is_none_char_ptr(T arg)244 static inline int z_cbprintf_cxx_is_none_char_ptr(T arg)
245 {
246 	ARG_UNUSED(arg);
247 
248 	return 1;
249 }
250 
251 /* C++ version for calculating argument size. */
z_cbprintf_cxx_arg_size(float f)252 static inline size_t z_cbprintf_cxx_arg_size(float f)
253 {
254 	ARG_UNUSED(f);
255 
256 	return sizeof(double);
257 }
258 
259 template < typename T >
z_cbprintf_cxx_arg_size(T arg)260 static inline size_t z_cbprintf_cxx_arg_size(T arg)
261 {
262 	ARG_UNUSED(arg);
263 
264 	return MAX(sizeof(T), sizeof(int));
265 }
266 
267 /* C++ version for storing arguments. */
z_cbprintf_cxx_store_arg(uint8_t * dst,float arg)268 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, float arg)
269 {
270 	double d = (double)arg;
271 	void *p = &d;
272 
273 	z_cbprintf_wcpy((int *)dst, (int *)p, sizeof(d) / sizeof(int));
274 }
275 
z_cbprintf_cxx_store_arg(uint8_t * dst,void * p)276 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, void *p)
277 {
278 	z_cbprintf_wcpy((int *)dst, (int *)&p, sizeof(p) / sizeof(int));
279 }
280 
z_cbprintf_cxx_store_arg(uint8_t * dst,char arg)281 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, char arg)
282 {
283 	int tmp = arg + 0;
284 
285 	z_cbprintf_wcpy((int *)dst, &tmp, 1);
286 }
287 
z_cbprintf_cxx_store_arg(uint8_t * dst,unsigned char arg)288 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, unsigned char arg)
289 {
290 	int tmp = arg + 0;
291 
292 	z_cbprintf_wcpy((int *)dst, &tmp, 1);
293 }
294 
z_cbprintf_cxx_store_arg(uint8_t * dst,signed char arg)295 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, signed char arg)
296 {
297 	int tmp = arg + 0;
298 
299 	z_cbprintf_wcpy((int *)dst, &tmp, 1);
300 }
301 
z_cbprintf_cxx_store_arg(uint8_t * dst,short arg)302 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, short arg)
303 {
304 	int tmp = arg + 0;
305 
306 	z_cbprintf_wcpy((int *)dst, &tmp, 1);
307 }
308 
z_cbprintf_cxx_store_arg(uint8_t * dst,unsigned short arg)309 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, unsigned short arg)
310 {
311 	int tmp = arg + 0;
312 
313 	z_cbprintf_wcpy((int *)dst, &tmp, 1);
314 }
315 
316 template < typename T >
z_cbprintf_cxx_store_arg(uint8_t * dst,T arg)317 static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, T arg)
318 {
319 	size_t wlen = z_cbprintf_cxx_arg_size(arg) / sizeof(int);
320 	void *p = &arg;
321 
322 	z_cbprintf_wcpy((int *)dst, (int *)p, wlen);
323 }
324 
325 /* C++ version for long double detection. */
z_cbprintf_cxx_is_longdouble(long double arg)326 static inline int z_cbprintf_cxx_is_longdouble(long double arg)
327 {
328 	ARG_UNUSED(arg);
329 	return 1;
330 }
331 
332 template < typename T >
z_cbprintf_cxx_is_longdouble(T arg)333 static inline int z_cbprintf_cxx_is_longdouble(T arg)
334 {
335 	ARG_UNUSED(arg);
336 
337 	return 0;
338 }
339 
340 /* C++ version for calculating argument alignment. */
z_cbprintf_cxx_alignment(float arg)341 static inline size_t z_cbprintf_cxx_alignment(float arg)
342 {
343 	ARG_UNUSED(arg);
344 
345 	return VA_STACK_ALIGN(double);
346 }
347 
z_cbprintf_cxx_alignment(double arg)348 static inline size_t z_cbprintf_cxx_alignment(double arg)
349 {
350 	ARG_UNUSED(arg);
351 
352 	return VA_STACK_ALIGN(double);
353 }
354 
z_cbprintf_cxx_alignment(long double arg)355 static inline size_t z_cbprintf_cxx_alignment(long double arg)
356 {
357 	ARG_UNUSED(arg);
358 
359 	return VA_STACK_ALIGN(long double);
360 }
361 
z_cbprintf_cxx_alignment(long long arg)362 static inline size_t z_cbprintf_cxx_alignment(long long arg)
363 {
364 	ARG_UNUSED(arg);
365 
366 	return VA_STACK_ALIGN(long long);
367 }
368 
z_cbprintf_cxx_alignment(unsigned long long arg)369 static inline size_t z_cbprintf_cxx_alignment(unsigned long long arg)
370 {
371 	ARG_UNUSED(arg);
372 
373 	return VA_STACK_ALIGN(long long);
374 }
375 
376 template < typename T >
z_cbprintf_cxx_alignment(T arg)377 static inline size_t z_cbprintf_cxx_alignment(T arg)
378 {
379 	return MAX(__alignof__(arg), VA_STACK_MIN_ALIGN);
380 }
381 
382 /* C++ version for checking if two arguments are same type */
383 template < typename T1, typename T2 >
384 struct z_cbprintf_cxx_is_same_type {
385 	enum {
386 		value = false
387 	};
388 };
389 
390 template < typename T >
391 struct z_cbprintf_cxx_is_same_type < T, T > {
392 	enum {
393 		value = true
394 	};
395 };
396 
397 template < typename T >
398 struct z_cbprintf_cxx_remove_reference {
399 	typedef T type;
400 };
401 
402 template < typename T >
403 struct z_cbprintf_cxx_remove_reference < T & > {
404 	typedef T type;
405 };
406 
407 #if __cplusplus >= 201103L
408 template < typename T >
409 struct z_cbprintf_cxx_remove_reference < T && > {
410 	typedef T type;
411 };
412 #endif
413 
414 template < typename T >
415 struct z_cbprintf_cxx_remove_cv {
416 	typedef T type;
417 };
418 
419 template < typename T >
420 struct z_cbprintf_cxx_remove_cv < const T > {
421 	typedef T type;
422 };
423 
424 template < typename T >
425 struct z_cbprintf_cxx_remove_cv < volatile T > {
426 	typedef T type;
427 };
428 
429 template < typename T >
430 struct z_cbprintf_cxx_remove_cv < const volatile T > {
431 	typedef T type;
432 };
433 
434 /* Determine if a type is an array */
435 template < typename T >
436 struct z_cbprintf_cxx_is_array {
437 	enum {
438 		value = false
439 	};
440 };
441 
442 template < typename T >
443 struct z_cbprintf_cxx_is_array < T[] > {
444 	enum {
445 		value = true
446 	};
447 };
448 
449 template < typename T, size_t N >
450 struct z_cbprintf_cxx_is_array < T[N] > {
451 	enum {
452 		value = true
453 	};
454 };
455 
456 /* Determine the type of elements in an array */
457 template < typename T >
458 struct z_cbprintf_cxx_remove_extent {
459 	typedef T type;
460 };
461 
462 template < typename T >
463 struct z_cbprintf_cxx_remove_extent < T[] > {
464 	typedef T type;
465 };
466 
467 template < typename T, size_t N >
468 struct z_cbprintf_cxx_remove_extent < T[N] > {
469 	typedef T type;
470 };
471 
472 #endif /* __cplusplus */
473 #endif /* ZEPHYR_INCLUDE_SYS_CBPRINTF_CXX_H_ */
474