Added parameter to CBPRINTF_STATIC_PACKAGE which indicates buffer alignment offset compared to CBPRINTF_PACKAGE_ALIGNMENT. When offset is set to 0, macro assumes that input buffer is aligned to CBPRINTF_PACKAGE_ALIGNMENT. When offset is positive, macro assumes that buffer address is shifted by given number of bytes to CBPRINTF_PACKAGE_ALIGNMENT alignment. Extended cbprintf_package to use len argument as alignment offset indicator when calculating length only (package pointer is null). Features are not available for xtensa platform which seems to require 16 byte alignment from the package. It is only an assumption due to lack of the documentation and may be fixed in the future. Feature allows to avoid unnecessary padding when package is part of a message and preceeded by a header of a known size. For example, message header on 32 bit architecture has 12 bytes, long doubles are not used so cbprintf requires 8 byte alignment. Without alignment offset indicator, package containing just a string with one argument would need 4 byte padding after the header and 4 byte padding after the package. Message would be 32 bytes long. With alignment offset indication both paddings are not needed and message is only 24 bytes long. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
423 lines
15 KiB
C
423 lines
15 KiB
C
/*
|
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_SYS_CBPRINTF_H_
|
|
#define ZEPHYR_INCLUDE_SYS_CBPRINTF_H_
|
|
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <toolchain.h>
|
|
|
|
#ifdef CONFIG_CBPRINTF_LIBC_SUBSTS
|
|
#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
|
|
*/
|
|
#ifndef Z_C_GENERIC
|
|
#if ((__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
|
|
#else
|
|
#define Z_C_GENERIC 0
|
|
#endif
|
|
#endif
|
|
|
|
/* Z_C_GENERIC is used there */
|
|
#include <sys/cbprintf_internal.h>
|
|
|
|
/**
|
|
* @defgroup cbprintf_apis Formatted Output APIs
|
|
* @ingroup support_apis
|
|
* @{
|
|
*/
|
|
|
|
/** @brief Required alignment of the buffer used for packaging. */
|
|
#ifdef __xtensa__
|
|
#define CBPRINTF_PACKAGE_ALIGNMENT 16
|
|
#else
|
|
#define CBPRINTF_PACKAGE_ALIGNMENT \
|
|
(IS_ENABLED(CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE) ? \
|
|
sizeof(long double) : MAX(sizeof(double), sizeof(long long)))
|
|
#endif
|
|
|
|
/** @brief Signature for a cbprintf callback function.
|
|
*
|
|
* This function expects two parameters:
|
|
*
|
|
* * @p c a character to output. The output behavior should be as if
|
|
* this was cast to an unsigned char.
|
|
* * @p ctx a pointer to an object that provides context for the
|
|
* output operation.
|
|
*
|
|
* The declaration does not specify the parameter types. This allows a
|
|
* function like @c fputc to be used without requiring all context pointers to
|
|
* be to a @c FILE object.
|
|
*
|
|
* @return the value of @p c cast to an unsigned char then back to
|
|
* int, or a negative error code that will be returned from
|
|
* cbprintf().
|
|
*/
|
|
typedef int (*cbprintf_cb)(/* int c, void *ctx */);
|
|
|
|
/** @brief Determine if string must be packaged in run time.
|
|
*
|
|
* Static packaging can be applied if size of the package can be determined
|
|
* at compile time. In general, package size can be determined at compile time
|
|
* if there are no string arguments which might be copied into package body if
|
|
* they are considered transient.
|
|
*
|
|
* @param skip number of read only string arguments in the parameter list. It
|
|
* shall be non-zero if there are known read only string arguments present
|
|
* in the string (e.g. function name prefix in the log message).
|
|
*
|
|
* @param ... String with arguments.
|
|
*
|
|
* @retval 1 if string must be packaged in run time.
|
|
* @retval 0 string can be statically packaged.
|
|
*/
|
|
#define CBPRINTF_MUST_RUNTIME_PACKAGE(skip, .../* fmt, ... */) \
|
|
Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, __VA_ARGS__)
|
|
|
|
/** @brief Statically package string.
|
|
*
|
|
* Build string package from formatted string. It assumes that formatted
|
|
* string is in the read only memory.
|
|
*
|
|
* If _Generic is not supported then runtime packaging is performed.
|
|
*
|
|
* @param packaged pointer to where the packaged data can be stored. Pass a null
|
|
* pointer to skip packaging but still calculate the total space required.
|
|
* The data stored here is relocatable, that is it can be moved to another
|
|
* contiguous block of memory. It must be aligned to the size of the longest
|
|
* argument. It is recommended to use CBPRINTF_PACKAGE_ALIGNMENT for alignment.
|
|
*
|
|
* @param inlen set to the number of bytes available at @p packaged. If
|
|
* @p packaged is NULL the value is ignored.
|
|
*
|
|
* @param outlen variable updated to the number of bytes required to completely
|
|
* store the packed information. If input buffer was too small it is set to
|
|
* -ENOSPC.
|
|
*
|
|
* @param align_offset input buffer alignment offset in bytes. Where offset 0
|
|
* means that buffer is aligned to CBPRINTF_PACKAGE_ALIGNMENT. Xtensa requires
|
|
* that @p packaged is aligned to CBPRINTF_PACKAGE_ALIGNMENT so it must be
|
|
* multiply of CBPRINTF_PACKAGE_ALIGNMENT or 0.
|
|
*
|
|
* @param ... formatted string with arguments. Format string must be constant.
|
|
*/
|
|
#define CBPRINTF_STATIC_PACKAGE(packaged, inlen, outlen, align_offset, \
|
|
... /* fmt, ... */) \
|
|
Z_CBPRINTF_STATIC_PACKAGE(packaged, inlen, outlen, \
|
|
align_offset, __VA_ARGS__)
|
|
|
|
/** @brief Capture state required to output formatted data later.
|
|
*
|
|
* Like cbprintf() but instead of processing the arguments and emitting the
|
|
* formatted results immediately all arguments are captured so this can be
|
|
* done in a different context, e.g. when the output function can block.
|
|
*
|
|
* In addition to the values extracted from arguments this will ensure that
|
|
* copies are made of the necessary portions of any string parameters that are
|
|
* not confirmed to be stored in read-only memory (hence assumed to be safe to
|
|
* refer to directly later).
|
|
*
|
|
* @param packaged pointer to where the packaged data can be stored. Pass a
|
|
* null pointer to store nothing but still calculate the total space required.
|
|
* The data stored here is relocatable, that is it can be moved to another
|
|
* contiguous block of memory. However, under condition that alignment is
|
|
* maintained. It must be aligned to at least the size of a pointer.
|
|
*
|
|
* @param len this must be set to the number of bytes available at @p packaged
|
|
* if it is not null. If @p packaged is null then it indicates hypothetical
|
|
* buffer alignment offset in bytes compared to CBPRINTF_PACKAGE_ALIGNMENT
|
|
* alignment. Buffer alignment offset impacts returned size of the package.
|
|
* Xtensa requires that buffer is always aligned to CBPRINTF_PACKAGE_ALIGNMENT
|
|
* so it must be multiply of CBPRINTF_PACKAGE_ALIGNMENT or 0 when @p packaged is
|
|
* null.
|
|
*
|
|
* @param format a standard ISO C format string with characters and conversion
|
|
* specifications.
|
|
*
|
|
* @param ... arguments corresponding to the conversion specifications found
|
|
* within @p format.
|
|
*
|
|
* @retval nonegative the number of bytes successfully stored at @p packaged.
|
|
* This will not exceed @p len.
|
|
* @retval -EINVAL if @p format is not acceptable
|
|
* @retval -EFAULT if @p packaged alignment is not acceptable
|
|
* @retval -ENOSPC if @p packaged was not null and the space required to store
|
|
* exceed @p len.
|
|
*/
|
|
__printf_like(3, 4)
|
|
int cbprintf_package(void *packaged,
|
|
size_t len,
|
|
const char *format,
|
|
...);
|
|
|
|
/** @brief Capture state required to output formatted data later.
|
|
*
|
|
* Like cbprintf() but instead of processing the arguments and emitting the
|
|
* formatted results immediately all arguments are captured so this can be
|
|
* done in a different context, e.g. when the output function can block.
|
|
*
|
|
* In addition to the values extracted from arguments this will ensure that
|
|
* copies are made of the necessary portions of any string parameters that are
|
|
* not confirmed to be stored in read-only memory (hence assumed to be safe to
|
|
* refer to directly later).
|
|
*
|
|
* @param packaged pointer to where the packaged data can be stored. Pass a
|
|
* null pointer to store nothing but still calculate the total space required.
|
|
* The data stored here is relocatable, that is it can be moved to another
|
|
* contiguous block of memory. The pointer must be aligned to a multiple of
|
|
* the largest element in the argument list.
|
|
*
|
|
* @param len this must be set to the number of bytes available at @p packaged.
|
|
* Ignored if @p packaged is NULL.
|
|
*
|
|
* @param format a standard ISO C format string with characters and conversion
|
|
* specifications.
|
|
*
|
|
* @param ap captured stack arguments corresponding to the conversion
|
|
* specifications found within @p format.
|
|
*
|
|
* @retval nonegative the number of bytes successfully stored at @p packaged.
|
|
* This will not exceed @p len.
|
|
* @retval -EINVAL if @p format is not acceptable
|
|
* @retval -ENOSPC if @p packaged was not null and the space required to store
|
|
* exceed @p len.
|
|
*/
|
|
int cbvprintf_package(void *packaged,
|
|
size_t len,
|
|
const char *format,
|
|
va_list ap);
|
|
|
|
/** @brief Generate the output for a previously captured format
|
|
* operation.
|
|
*
|
|
* @param out the function used to emit each generated character.
|
|
*
|
|
* @param ctx context provided when invoking out
|
|
*
|
|
* @param packaged the data required to generate the formatted output, as
|
|
* captured by cbprintf_package() or cbvprintf_package(). The alignment
|
|
* requirement on this data is the same as when it was initially created.
|
|
*
|
|
* @note Memory indicated by @p packaged will be modified in a non-destructive
|
|
* way, meaning that it could still be reused with this function again.
|
|
*
|
|
* @return the number of characters printed, or a negative error value
|
|
* returned from invoking @p out.
|
|
*/
|
|
int cbpprintf(cbprintf_cb out,
|
|
void *ctx,
|
|
void *packaged);
|
|
|
|
/** @brief *printf-like output through a callback.
|
|
*
|
|
* This is essentially printf() except the output is generated
|
|
* character-by-character using the provided @p out function. This allows
|
|
* formatting text of unbounded length without incurring the cost of a
|
|
* temporary buffer.
|
|
*
|
|
* All formatting specifiers of C99 are recognized, and most are supported if
|
|
* the functionality is enabled.
|
|
*
|
|
* @note The functionality of this function is significantly reduced
|
|
* when @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param out the function used to emit each generated character.
|
|
*
|
|
* @param ctx context provided when invoking out
|
|
*
|
|
* @param format a standard ISO C format string with characters and conversion
|
|
* specifications.
|
|
*
|
|
* @param ... arguments corresponding to the conversion specifications found
|
|
* within @p format.
|
|
*
|
|
* @return the number of characters printed, or a negative error value
|
|
* returned from invoking @p out.
|
|
*/
|
|
__printf_like(3, 4)
|
|
int cbprintf(cbprintf_cb out, void *ctx, const char *format, ...);
|
|
|
|
/** @brief varargs-aware *printf-like output through a callback.
|
|
*
|
|
* This is essentially vsprintf() except the output is generated
|
|
* character-by-character using the provided @p out function. This allows
|
|
* formatting text of unbounded length without incurring the cost of a
|
|
* temporary buffer.
|
|
*
|
|
* @note This function is available only when
|
|
* @option{CONFIG_CBPRINTF_LIBC_SUBSTS} is selected.
|
|
*
|
|
* @note The functionality of this function is significantly reduced when
|
|
* @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param out the function used to emit each generated character.
|
|
*
|
|
* @param ctx context provided when invoking out
|
|
*
|
|
* @param format a standard ISO C format string with characters and conversion
|
|
* specifications.
|
|
*
|
|
* @param ap a reference to the values to be converted.
|
|
*
|
|
* @return the number of characters generated, or a negative error value
|
|
* returned from invoking @p out.
|
|
*/
|
|
int cbvprintf(cbprintf_cb out, void *ctx, const char *format, va_list ap);
|
|
|
|
#ifdef CONFIG_CBPRINTF_LIBC_SUBSTS
|
|
|
|
/** @brief fprintf using Zephyrs cbprintf infrastructure.
|
|
*
|
|
* @note This function is available only when
|
|
* @option{CONFIG_CBPRINTF_LIBC_SUBSTS} is selected.
|
|
*
|
|
* @note The functionality of this function is significantly reduced
|
|
* when @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param stream the stream to which the output should be written.
|
|
*
|
|
* @param format a standard ISO C format string with characters and
|
|
* conversion specifications.
|
|
*
|
|
* @param ... arguments corresponding to the conversion specifications found
|
|
* within @p format.
|
|
*
|
|
* return The number of characters printed.
|
|
*/
|
|
__printf_like(2, 3)
|
|
int fprintfcb(FILE * stream, const char *format, ...);
|
|
|
|
/** @brief vfprintf using Zephyrs cbprintf infrastructure.
|
|
*
|
|
* @note This function is available only when
|
|
* @option{CONFIG_CBPRINTF_LIBC_SUBSTS} is selected.
|
|
*
|
|
* @note The functionality of this function is significantly reduced when
|
|
* @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param stream the stream to which the output should be written.
|
|
*
|
|
* @param format a standard ISO C format string with characters and conversion
|
|
* specifications.
|
|
*
|
|
* @param ap a reference to the values to be converted.
|
|
*
|
|
* @return The number of characters printed.
|
|
*/
|
|
int vfprintfcb(FILE *stream, const char *format, va_list ap);
|
|
|
|
/** @brief printf using Zephyrs cbprintf infrastructure.
|
|
*
|
|
* @note This function is available only when
|
|
* @option{CONFIG_CBPRINTF_LIBC_SUBSTS} is selected.
|
|
*
|
|
* @note The functionality of this function is significantly reduced
|
|
* when @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param format a standard ISO C format string with characters and
|
|
* conversion specifications.
|
|
*
|
|
* @param ... arguments corresponding to the conversion specifications found
|
|
* within @p format.
|
|
*
|
|
* @return The number of characters printed.
|
|
*/
|
|
__printf_like(1, 2)
|
|
int printfcb(const char *format, ...);
|
|
|
|
/** @brief vprintf using Zephyrs cbprintf infrastructure.
|
|
*
|
|
* @note This function is available only when
|
|
* @option{CONFIG_CBPRINTF_LIBC_SUBSTS} is selected.
|
|
*
|
|
* @note The functionality of this function is significantly reduced when
|
|
* @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param format a standard ISO C format string with characters and conversion
|
|
* specifications.
|
|
*
|
|
* @param ap a reference to the values to be converted.
|
|
*
|
|
* @return The number of characters printed.
|
|
*/
|
|
int vprintfcb(const char *format, va_list ap);
|
|
|
|
/** @brief snprintf using Zephyrs cbprintf infrastructure.
|
|
*
|
|
* @note This function is available only when
|
|
* @option{CONFIG_CBPRINTF_LIBC_SUBSTS} is selected.
|
|
*
|
|
* @note The functionality of this function is significantly reduced
|
|
* when @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param str where the formatted content should be written
|
|
*
|
|
* @param size maximum number of chaacters for the formatted output,
|
|
* including the terminating null byte.
|
|
*
|
|
* @param format a standard ISO C format string with characters and
|
|
* conversion specifications.
|
|
*
|
|
* @param ... arguments corresponding to the conversion specifications found
|
|
* within @p format.
|
|
*
|
|
* @return The number of characters that would have been written to @p
|
|
* str, excluding the terminating null byte. This is greater than the
|
|
* number actually written if @p size is too small.
|
|
*/
|
|
__printf_like(3, 4)
|
|
int snprintfcb(char *str, size_t size, const char *format, ...);
|
|
|
|
/** @brief vsnprintf using Zephyrs cbprintf infrastructure.
|
|
*
|
|
* @note This function is available only when
|
|
* @option{CONFIG_CBPRINTF_LIBC_SUBSTS} is selected.
|
|
*
|
|
* @note The functionality of this function is significantly reduced when
|
|
* @option{CONFIG_CBPRINTF_NANO} is selected.
|
|
*
|
|
* @param str where the formatted content should be written
|
|
*
|
|
* @param size maximum number of chaacters for the formatted output, including
|
|
* the terminating null byte.
|
|
*
|
|
* @param format a standard ISO C format string with characters and conversion
|
|
* specifications.
|
|
*
|
|
* @param ap a reference to the values to be converted.
|
|
*
|
|
* @return The number of characters that would have been written to @p
|
|
* str, excluding the terminating null byte. This is greater than the
|
|
* number actually written if @p size is too small.
|
|
*/
|
|
int vsnprintfcb(char *str, size_t size, const char *format, va_list ap);
|
|
|
|
#endif /* CONFIG_CBPRINTF_LIBC_SUBSTS */
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* ZEPHYR_INCLUDE_SYS_CBPRINTF_H_ */
|