Skip to content

Commit 7534d1f

Browse files
committed
lib: cbprintf: add support for deferred formatting
In applications like logging the call site where arguments to formatting are available may not be suitable for performing the formatting, e.g. when the output operation can sleep. Add API that supports capturing data that may be transient into a buffer that can be saved, and API that then produces the output later using the packaged arguments. Signed-off-by: Peter Bigot <[email protected]>
1 parent 7e0e446 commit 7534d1f

File tree

4 files changed

+857
-9
lines changed

4 files changed

+857
-9
lines changed

include/sys/cbprintf.h

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <stdarg.h>
1111
#include <stddef.h>
12+
#include <stdint.h>
1213
#include <toolchain.h>
1314

1415
#ifdef CONFIG_CBPRINTF_LIBC_SUBSTS
@@ -44,6 +45,108 @@ extern "C" {
4445
*/
4546
typedef int (*cbprintf_cb)(/* int c, void *ctx */);
4647

48+
/** @brief Capture state required to output formatted data later.
49+
*
50+
* Like cbprintf() but instead of processing the arguments and emitting the
51+
* formatted results immediately all arguments are captured so this can be
52+
* done in a different context, e.g. when the output function can block.
53+
*
54+
* In addition to the values extracted from arguments this will ensure that
55+
* copies are made of the necessary portions of any string parameters that are
56+
* not confirmed to be stored in read-only memory (hence assumed to be safe to
57+
* refer to directly later).
58+
*
59+
* @note This function is available only when `CONFIG_CBPRINTF_COMPLETE` is
60+
* selected.
61+
*
62+
* @param packaged pointer to where the packaged data can be stored. Pass a
63+
* null pointer to store nothing but still calculate the total space required.
64+
* The data stored here is relocatable, that is it can be moved to another
65+
* contiguous block of memory.
66+
*
67+
* @param len on input this must be set to the number of bytes available at @p
68+
* packaged. If @p packaged is NULL the input value is ignored. On output
69+
* the referenced value will be updated to the number of bytes required to
70+
* completely store the packed information. The @p len parameter must not be
71+
* null.
72+
*
73+
* @param format a standard ISO C format string with characters and conversion
74+
* specifications.
75+
*
76+
* @param ... arguments corresponding to the conversion specifications found
77+
* within @p format.
78+
*
79+
* @retval nonegative the number of bytes successfully stored at @p packaged.
80+
* This will not exceed the input value of @p *len.
81+
* @retval -EINVAL if @p format or @p len are not acceptable
82+
* @retval -ENOSPC if @p packaged was not null and the space required to store
83+
* exceed the input value of @p *len.
84+
*/
85+
__printf_like(3, 4)
86+
int cbprintf_package(uint8_t *packaged,
87+
size_t *len,
88+
const char *format,
89+
...);
90+
91+
/** @brief Capture state required to output formatted data later.
92+
*
93+
* Like cbprintf() but instead of processing the arguments and emitting the
94+
* formatted results immediately all arguments are captured so this can be
95+
* done in a different context, e.g. when the output function can block.
96+
*
97+
* In addition to the values extracted from arguments this will ensure that
98+
* copies are made of the necessary portions of any string parameters that are
99+
* not confirmed to be stored in read-only memory (hence assumed to be safe to
100+
* refer to directly later).
101+
*
102+
* @note This function is available only when `CONFIG_CBPRINTF_COMPLETE` is
103+
* selected.
104+
*
105+
* @param packaged pointer to where the packaged data can be stored. Pass a
106+
* null pointer to store nothing but still calculate the total space required.
107+
* The data stored here is relocatable, that is it can be moved to another
108+
* contiguous block of memory.
109+
*
110+
* @param len on input this must be set to the number of bytes available at @p
111+
* packaged. If @p packaged is NULL the input value is ignored. On output
112+
* the referenced value will be updated to the number of bytes required to
113+
* completely store the packed information. The @p len parameter must not be
114+
* null.
115+
*
116+
* @param format a standard ISO C format string with characters and conversion
117+
* specifications.
118+
*
119+
* @param ap captured stack arguments corresponding to the conversion
120+
* specifications found within @p format.
121+
*
122+
* @retval nonegative the number of bytes successfully stored at @p packaged.
123+
* This will not exceed the input value of @p *len.
124+
* @retval -EINVAL if @p format or @p len are not acceptable
125+
* @retval -ENOSPC if @p packaged was not null and the space required to store
126+
* exceed the input value of @p *len.
127+
*/
128+
int cbvprintf_package(uint8_t *packaged,
129+
size_t *len,
130+
const char *format,
131+
va_list ap);
132+
133+
/** @brief Generate the output for a previously captured format
134+
* operation.
135+
*
136+
* @param out the function used to emit each generated character.
137+
*
138+
* @param ctx context provided when invoking out
139+
*
140+
* @param packaged the data required to generate the formatted output, as
141+
* captured by cbprintf_package() or cbvprintf_package().
142+
*
143+
* @return the number of characters printed, or a negative error value
144+
* returned from invoking @p out.
145+
*/
146+
int cbpprintf(cbprintf_cb out,
147+
void *ctx,
148+
const uint8_t *packaged);
149+
47150
/** @brief *printf-like output through a callback.
48151
*
49152
* This is essentially printf() except the output is generated

0 commit comments

Comments
 (0)