Skip to content

Commit d7d9b71

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 70b3388 commit d7d9b71

File tree

4 files changed

+826
-8
lines changed

4 files changed

+826
-8
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 __cplusplus
@@ -40,6 +41,108 @@ extern "C" {
4041
*/
4142
typedef int (*cbprintf_cb)(/* int c, void *ctx */);
4243

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

0 commit comments

Comments
 (0)