Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3a105ad
lib: cbprintf: fix mishandling of precision string output
pabigot Dec 11, 2020
693af64
tests: cbprintf: sanitize language
pabigot Dec 12, 2020
8db6d78
tests: cbprintf: make skip messages consistent
pabigot Dec 12, 2020
ef4d8fd
lib: cbprintf: improve coverage
pabigot Dec 12, 2020
bcaa4aa
lib: cbprintf: remove cbprintf_arglen
pabigot Dec 12, 2020
7f98034
lib: cbprintf: document length modifiers
pabigot Dec 12, 2020
5b156fc
lib: cbprintf: refactor for upcoming enhancement
pabigot Dec 11, 2020
1b6dd8d
lib: cbprintf: refactor handling of dynamic format flags
pabigot Dec 12, 2020
c5d5562
lib: cbprintf: factor out core conversion implementation
pabigot Dec 12, 2020
70b3388
tests: increase stack requirements on some tests
pabigot Dec 13, 2020
d7d9b71
lib: cbprintf: add support for deferred formatting
pabigot Dec 12, 2020
17a85ed
lib: os: cbprintf: Fix double handling in package
nordic-krch Dec 16, 2020
0c85482
lib: os: cbprintf: Use int for packaging HH and H values
nordic-krch Dec 16, 2020
90e8f01
lib: os: cbprintf: Use wint_t for packaging %lc
nordic-krch Dec 16, 2020
6d7fb95
lib: os: cbprintf: Use wchar_t instead of wint_t
nordic-krch Dec 21, 2020
4784db5
sys: util: Add fast version of FOR_EACH_x, GET_ARG and GET_ARGS_LESS
nordic-krch Feb 2, 2021
fa21774
tests: unit: util: Add test for fast versions of loop macros
nordic-krch Feb 2, 2021
53d2162
lib: os: cbprintf: Add macros for static packaging
nordic-krch Dec 16, 2020
c9581d0
tests: unit: cbprintf: Extend test to support static packaging
nordic-krch Dec 16, 2020
b2688a5
sys: cbprintf: Add pragma to supress warning during packaging
nordic-krch Feb 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 179 additions & 20 deletions include/sys/cbprintf.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <toolchain.h>
#include <sys/cbprintf_internal.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -21,6 +23,14 @@ extern "C" {
* @{
*/

/**@defgroup CBPRINTF_PACKAGE_FLAGS packaging flags.
* @{ */

/** @brief Indicate that format string is packaged as pointer. */
#define CBPRINTF_PACKAGE_FMT_AS_PTR BIT(0)

/**@} */

/** @brief Signature for a cbprintf callback function.
*
* This function expects two parameters:
Expand All @@ -40,6 +50,175 @@ extern "C" {
*/
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 and 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).
* @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 based on formatted string. Macro produces same package
* as if @ref cbprintf_package was used with CBPRINTF_PACKAGE_FMT_AS_PTR set.
*
* @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.

* @param len on input this must be set to the number of bytes available at @p
* packaged. If @p packaged is NULL the input value is ignored. On output
* the referenced value will be updated to the number of bytes required to
* completely store the packed information. The @p len parameter must not be
* null.
*
* @param fmt_as_ptr Set to 1 to package format string as void pointer without
* header. It optimizes package size for read only strings. It must be a
* constant value at compile time.
*
* @param ... formatted string with arguments. Format string must be constant.
*/
#define CBPRINTF_STATIC_PACKAGE(packaged, len, fmt_as_ptr, ... /* fmt, ... */) \
Z_CBPRINTF_STATIC_PACKAGE(packaged, len, fmt_as_ptr, __VA_ARGS__)

/** @brief Calculate package size at compile time.
*
* @param name Name of the variable that will be contain package size.
*
* @param fmt_as_ptr Set to 1 to package format string as void pointer without
* header. It optimizes package size for read only strings.
*
* @param ... String with arguments.
*
* @return Calculated package size. As it is determined at compile time it can
* be assigned to a const variable.
*/
#define CBPRINTF_STATIC_PACKAGE_SIZE(name, fmt_as_ptr, ... /* fmt, ... */) \
Z_CBPRINTF_STATIC_PACKAGE_SIZE(name, fmt_as_ptr, __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).
*
* @note This function is available only when `CONFIG_CBPRINTF_COMPLETE` is
* selected.
*
* @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.
*
* @param len on input this must be set to the number of bytes available at @p
* packaged. If @p packaged is NULL the input value is ignored. On output
* the referenced value will be updated to the number of bytes required to
* completely store the packed information. The @p len parameter must not be
* null.
*
* @param flags Flags. See @ref CBPRINTF_PACKAGE_FLAGS.
*
* @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 the input value of @p *len.
* @retval -EINVAL if @p format or @p len are not acceptable
* @retval -ENOSPC if @p packaged was not null and the space required to store
* exceed the input value of @p *len.
*/
__printf_like(4, 5)
int cbprintf_package(uint8_t *packaged,
size_t *len,
uint32_t flags,
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).
*
* @note This function is available only when `CONFIG_CBPRINTF_COMPLETE` is
* selected.
*
* @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.
*
* @param len on input this must be set to the number of bytes available at @p
* packaged. If @p packaged is NULL the input value is ignored. On output
* the referenced value will be updated to the number of bytes required to
* completely store the packed information. The @p len parameter must not be
* null.
*
* @param flags Flags. See @ref CBPRINTF_PACKAGE_FLAGS.
*
* @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 the input value of @p *len.
* @retval -EINVAL if @p format or @p len are not acceptable
* @retval -ENOSPC if @p packaged was not null and the space required to store
* exceed the input value of @p *len.
*/
int cbvprintf_package(uint8_t *packaged,
size_t *len,
uint32_t flags,
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 flags Flags. See @ref CBPRINTF_PACKAGE_FLAGS.
*
* @param packaged the data required to generate the formatted output, as
* captured by cbprintf_package() or cbvprintf_package().
*
* @return the number of characters printed, or a negative error value
* returned from invoking @p out.
*/
int cbpprintf(cbprintf_cb out,
void *ctx,
uint32_t flags,
const uint8_t *packaged);

/** @brief *printf-like output through a callback.
*
* This is essentially printf() except the output is generated
Expand Down Expand Up @@ -69,26 +248,6 @@ typedef int (*cbprintf_cb)(/* int c, void *ctx */);
__printf_like(3, 4)
int cbprintf(cbprintf_cb out, void *ctx, const char *format, ...);

/** @brief Calculate the number of words required for arguments to a cbprintf
* format specification.
*
* This can be used in cases where the arguments must be copied off the stack
* into separate storage for processing the conversion in another context.
*
* @note The length returned does not count bytes. It counts native words
* defined as the size of an `int`.
*
* @note If `CONFIG_CBPRINTF_NANO` is selected the count will be incorrect if
* any passed arguments require more than one `int`.
*
* @param format a standard ISO C format string with characters and conversion
* specifications.
*
* @return the number of `int` elements required to provide all arguments
* required for the conversion.
*/
size_t cbprintf_arglen(const char *format);

/** @brief varargs-aware *printf-like output through a callback.
*
* This is essentially vsprintf() except the output is generated
Expand Down
Loading