lib: os: cbprintf: Improve C++ support in static packaging
Added C++ replacements for macros that are using _Generic keyword. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
caa3328cc7
commit
6f227698bb
3 changed files with 178 additions and 21 deletions
|
@ -16,17 +16,16 @@
|
|||
#include <stdio.h>
|
||||
#endif /* CONFIG_CBPRINTF_LIBC_SUBSTS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Determine if _Generic is supported.
|
||||
* In general it's a C11 feature but it was added also in:
|
||||
* - GCC 4.9.0 https://gcc.gnu.org/gcc-4.9/changes.html
|
||||
* - Clang 3.0 https://releases.llvm.org/3.0/docs/ClangReleaseNotes.html
|
||||
*
|
||||
* @note Z_C_GENERIC is also set for C++ where functionality is implemented
|
||||
* using overloading and templates.
|
||||
*/
|
||||
#ifndef Z_C_GENERIC
|
||||
#if !defined(__cplusplus) && (((__STDC_VERSION__ >= 201112L) || \
|
||||
#if defined(__cplusplus) || (((__STDC_VERSION__ >= 201112L) || \
|
||||
((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40900) || \
|
||||
((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 30000)))
|
||||
#define Z_C_GENERIC 1
|
||||
|
@ -38,6 +37,10 @@ extern "C" {
|
|||
/* Z_C_GENERIC is used there */
|
||||
#include <sys/cbprintf_internal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup cbprintf_apis Formatted Output APIs
|
||||
* @ingroup support_apis
|
||||
|
|
131
include/sys/cbprintf_cxx.h
Normal file
131
include/sys/cbprintf_cxx.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_SYS_CBPRINTF_CXX_H_
|
||||
#define ZEPHYR_INCLUDE_SYS_CBPRINTF_CXX_H_
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* C++ version for detecting a pointer to a string. */
|
||||
static inline int z_cbprintf_cxx_is_pchar(char *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int z_cbprintf_cxx_is_pchar(const char *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int z_cbprintf_cxx_is_pchar(volatile char *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int z_cbprintf_cxx_is_pchar(const volatile char *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int z_cbprintf_cxx_is_pchar(wchar_t *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int z_cbprintf_cxx_is_pchar(const wchar_t *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int z_cbprintf_cxx_is_pchar(volatile wchar_t *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int z_cbprintf_cxx_is_pchar(const volatile wchar_t *)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
static inline int z_cbprintf_cxx_is_pchar(T arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* C++ version for calculating argument size. */
|
||||
static inline size_t z_cbprintf_cxx_arg_size(float f)
|
||||
{
|
||||
return sizeof(double);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
static inline size_t z_cbprintf_cxx_arg_size(T arg)
|
||||
{
|
||||
return sizeof(arg + 0);
|
||||
}
|
||||
|
||||
/* C++ version for storing arguments. */
|
||||
static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, float arg)
|
||||
{
|
||||
double d = (double)arg;
|
||||
|
||||
z_cbprintf_wcpy((int *)dst, (int *)&d, sizeof(d) / sizeof(int));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
static inline void z_cbprintf_cxx_store_arg(uint8_t *dst, T arg)
|
||||
{
|
||||
size_t wlen = z_cbprintf_cxx_arg_size(arg) / sizeof(int);
|
||||
|
||||
z_cbprintf_wcpy((int *)dst, (int *)&arg, wlen);
|
||||
}
|
||||
|
||||
/* C++ version for long double detection. */
|
||||
static inline int z_cbprintf_cxx_is_longdouble(long double arg)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
static inline int z_cbprintf_cxx_is_longdouble(T arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* C++ version for caluculating argument alignment. */
|
||||
static inline size_t z_cbprintf_cxx_alignment(float arg)
|
||||
{
|
||||
return VA_STACK_ALIGN(double);
|
||||
}
|
||||
|
||||
static inline size_t z_cbprintf_cxx_alignment(double arg)
|
||||
{
|
||||
return VA_STACK_ALIGN(double);
|
||||
}
|
||||
|
||||
static inline size_t z_cbprintf_cxx_alignment(long double arg)
|
||||
{
|
||||
return VA_STACK_ALIGN(long double);
|
||||
}
|
||||
|
||||
static inline size_t z_cbprintf_cxx_alignment(long long arg)
|
||||
{
|
||||
return VA_STACK_ALIGN(long long);
|
||||
}
|
||||
|
||||
static inline size_t z_cbprintf_cxx_alignment(unsigned long long arg)
|
||||
{
|
||||
return VA_STACK_ALIGN(long long);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
static inline size_t z_cbprintf_cxx_alignment(T arg)
|
||||
{
|
||||
return MAX(__alignof__(arg), VA_STACK_MIN_ALIGN);
|
||||
}
|
||||
|
||||
#endif /* __cplusplus */
|
||||
#endif /* ZEPHYR_INCLUDE_SYS_CBPRINTF_CXX_H_ */
|
|
@ -15,10 +15,6 @@
|
|||
#include <sys/util.h>
|
||||
#include <sys/__assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Special alignment cases
|
||||
*/
|
||||
|
@ -49,6 +45,20 @@ extern "C" {
|
|||
#define VA_STACK_ALIGN(type) MAX(VA_STACK_MIN_ALIGN, __alignof__(type))
|
||||
#endif
|
||||
|
||||
static inline void z_cbprintf_wcpy(int *dst, int *src, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
#include <sys/cbprintf_cxx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__sparc__)
|
||||
/* The SPARC V8 ABI guarantees that the arguments of a variable argument
|
||||
* list function are stored on the stack at addresses which are 32-bit
|
||||
|
@ -71,6 +81,9 @@ extern "C" {
|
|||
*
|
||||
* @return 1 if char * or wchar_t *, 0 otherwise.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define Z_CBPRINTF_IS_PCHAR(x) z_cbprintf_cxx_is_pchar(x)
|
||||
#else
|
||||
#define Z_CBPRINTF_IS_PCHAR(x) _Generic((x), \
|
||||
char * : 1, \
|
||||
const char * : 1, \
|
||||
|
@ -82,6 +95,7 @@ extern "C" {
|
|||
const volatile wchar_t * : 1, \
|
||||
default : \
|
||||
0)
|
||||
#endif
|
||||
|
||||
/** @brief Calculate number of char * or wchar_t * arguments in the arguments.
|
||||
*
|
||||
|
@ -123,6 +137,9 @@ extern "C" {
|
|||
*
|
||||
* @return Number of bytes used for storing the argument.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define Z_CBPRINTF_ARG_SIZE(v) z_cbprintf_cxx_arg_size(v)
|
||||
#else
|
||||
#define Z_CBPRINTF_ARG_SIZE(v) \
|
||||
_Generic((v), \
|
||||
float : sizeof(double), \
|
||||
|
@ -130,13 +147,7 @@ extern "C" {
|
|||
/* coverity[bad_sizeof] */ \
|
||||
sizeof((v) + 0) \
|
||||
)
|
||||
|
||||
static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @brief Promote and store argument in the buffer.
|
||||
*
|
||||
|
@ -144,6 +155,9 @@ static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
|||
*
|
||||
* @param arg Argument.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define Z_CBPRINTF_STORE_ARG(buf, arg) z_cbprintf_cxx_store_arg(buf, arg)
|
||||
#else
|
||||
#define Z_CBPRINTF_STORE_ARG(buf, arg) do { \
|
||||
if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { \
|
||||
/* If required, copy arguments by word to avoid unaligned access.*/ \
|
||||
|
@ -154,7 +168,7 @@ static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
|||
0.0); \
|
||||
size_t arg_size = Z_CBPRINTF_ARG_SIZE(arg); \
|
||||
size_t _wsize = arg_size / sizeof(int); \
|
||||
cbprintf_wcpy((int *)buf, \
|
||||
z_cbprintf_wcpy((int *)buf, \
|
||||
(int *) _Generic((arg) + 0, float : &_d, default : &_v), \
|
||||
_wsize); \
|
||||
} else { \
|
||||
|
@ -176,6 +190,7 @@ static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
|||
(const void **)buf) = arg; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/** @brief Return alignment needed for given argument.
|
||||
*
|
||||
|
@ -183,6 +198,9 @@ static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
|||
*
|
||||
* @return Alignment in bytes.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define Z_CBPRINTF_ALIGNMENT(_arg) z_cbprintf_cxx_alignment(_arg)
|
||||
#else
|
||||
#define Z_CBPRINTF_ALIGNMENT(_arg) \
|
||||
MAX(_Generic((_arg) + 0, \
|
||||
float : VA_STACK_ALIGN(double), \
|
||||
|
@ -192,6 +210,7 @@ static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
|||
unsigned long long : VA_STACK_ALIGN(long long), \
|
||||
default : \
|
||||
__alignof__((_arg) + 0)), VA_STACK_MIN_ALIGN)
|
||||
#endif
|
||||
|
||||
/** @brief Detect long double variable.
|
||||
*
|
||||
|
@ -199,8 +218,12 @@ static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
|||
*
|
||||
* @return 1 if @p x is a long double, 0 otherwise.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define Z_CBPRINTF_IS_LONGDOUBLE(x) z_cbprintf_cxx_is_longdouble(x)
|
||||
#else
|
||||
#define Z_CBPRINTF_IS_LONGDOUBLE(x) \
|
||||
_Generic((x) + 0, long double : 1, default : 0)
|
||||
#endif
|
||||
|
||||
/** @brief Safely package arguments to a buffer.
|
||||
*
|
||||
|
@ -227,7 +250,7 @@ static inline void cbprintf_wcpy(int *dst, int *src, size_t len)
|
|||
_align_offset += sizeof(int); \
|
||||
} \
|
||||
uint32_t _arg_size = Z_CBPRINTF_ARG_SIZE(_arg); \
|
||||
if (_buf && _idx < _max) { \
|
||||
if (_buf && _idx < (int)_max) { \
|
||||
Z_CBPRINTF_STORE_ARG(&_buf[_idx], _arg); \
|
||||
} \
|
||||
_idx += _arg_size; \
|
||||
|
@ -302,7 +325,7 @@ do { \
|
|||
"Buffer must be aligned."); \
|
||||
} \
|
||||
uint8_t *_pbuf = buf; \
|
||||
size_t _pmax = (buf != NULL) ? _inlen : SIZE_MAX; \
|
||||
size_t _pmax = (buf != NULL) ? _inlen : INT32_MAX; \
|
||||
int _pkg_len = 0; \
|
||||
int _pkg_offset = _align_offset; \
|
||||
union z_cbprintf_hdr *_len_loc; \
|
||||
|
@ -317,11 +340,11 @@ do { \
|
|||
/* Pack remaining arguments */\
|
||||
FOR_EACH(Z_CBPRINTF_PACK_ARG, (;), __VA_ARGS__);\
|
||||
/* Store length */ \
|
||||
_outlen = (_pkg_len > _pmax) ? -ENOSPC : _pkg_len; \
|
||||
_outlen = (_pkg_len > (int)_pmax) ? -ENOSPC : _pkg_len; \
|
||||
/* Store length in the header, set number of dumped strings to 0 */ \
|
||||
if (_pbuf) { \
|
||||
union z_cbprintf_hdr hdr = { \
|
||||
.desc = {.len = _pkg_len / sizeof(int) } \
|
||||
.desc = {.len = (uint8_t)(_pkg_len / sizeof(int)) } \
|
||||
}; \
|
||||
*_len_loc = hdr; \
|
||||
} \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue