summaryrefslogtreecommitdiff
path: root/include/printf.h
blob: b63208f84dde857848ca8c49245388f513b715b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/* Copyright 2012 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* Printf-like functionality for Chrome EC */

#ifndef __CROS_EC_PRINTF_H
#define __CROS_EC_PRINTF_H

#include <stdarg.h> /* For va_list */
#include <stdbool.h>
#include <stddef.h> /* For size_t */
#include "common.h"
#include "console.h"

/* The declaration of snprintf is changed to crec_snprintf for Zephyr,
 * so include stdio.h from Zephyr.
 */
#ifdef CONFIG_ZEPHYR
#include <stdio.h>
#endif

/**
 * Buffer size in bytes large enough to hold the largest possible timestamp.
 */
#define PRINTF_TIMESTAMP_BUF_SIZE 22

/*
 * Printf formatting: % [flags] [width] [.precision] [length] [type]
 *
 * Flags may be any/all of the following, and must occur in the following
 * order if present:
 *   - '0' = prefixed with 0's instead of spaces (%08x)
 *   - '-' = left-justify instead of right-justify (%-5s)
 *   - '+' = prefix positive value with '+' (%+d). Write '%-+' instead of
 *           '%+-' when used with left-justification. Ignored when
 *           used with unsigned integer types or non-integer types.
 *
 * Width is the minimum output width, and may be:
 *   - A number ("0" - "255")
 *   - '*' = use next integer argument as width
 *
 * Precision must be preceded by a decimal point, and may be:
 *   - A number ("0" - "255")
 *   - '*' = use next integer argument as precision
 *
 * For integers, precision will put a decimal point before that many digits.
 * So snprintf(buf, size, "%.6d", 123) sets buf="0.000123".  This is most
 * useful for printing times, voltages, and currents.
 *
 * Length may be:
 *   - 'l'  = DEPRECATED, do not use (see crbug.com/984041)
 *   - 'll' = integer is 64-bit
 *   - 'z'  = integer is sizeof(size_t)
 *
 * Type may be:
 *   - 'c' - character
 *   - 's' - null-terminated ASCII string
 *   - 'd' - signed integer
 *   - 'i' - signed integer (if CONFIG_PRINTF_LONG_IS_32BITS is enabled)
 *   - 'u' - unsigned integer
 *   - 'x' - unsigned integer, print as lower-case hexadecimal
 *   - 'X' - unsigned integer, print as upper-case hexadecimal
 *   - 'b' - unsigned integer, print as binary
 *   - 'p' - pointer
 */

#ifndef HIDE_EC_STDLIB

/**
 * Print formatted output to a function, like vfprintf()
 *
 * @param addchar	Function to be called for each character added.
 *			Will be passed the same context passed to vfnprintf(),
 *			and the character to add.  Should return 0 if the
 *			character was accepted or non-zero if the character
 *			was dropped due to overflow.
 * @param context	Context pointer to pass to addchar()
 * @param format	Format string (see above for acceptable formats)
 * @param args		Parameters
 * @return EC_SUCCESS, or EC_ERROR_OVERFLOW if the output was truncated.
 */
__stdlib_compat int vfnprintf(int (*addchar)(void *context, int c),
			      void *context, const char *format, va_list args);

#ifndef CONFIG_ZEPHYR
#define snprintf crec_snprintf
#define vsnprintf crec_vsnprintf
#endif

/**
 * Print formatted outut to a string.
 *
 * Guarantees null-termination if size!=0.
 *
 * @param str		Destination string
 * @param size		Size of destination in bytes
 * @param format	Format string
 * @return EC_SUCCESS, or EC_ERROR_OVERFLOW if the output was truncated.
 */
__attribute__((__format__(__printf__, 3, 4)))
__warn_unused_result __stdlib_compat int
crec_snprintf(char *str, size_t size, const char *format, ...);

/**
 * Print formatted output to a string.
 *
 * Guarantees null-termination if size!=0.
 *
 * @param str		Destination string
 * @param size		Size of destination in bytes
 * @param format	Format string
 * @param args		Parameters
 * @return The string length written to str, or a negative value on error.
 *         The negative values can be -EC_ERROR_INVAL or -EC_ERROR_OVERFLOW.
 */
__warn_unused_result __stdlib_compat int
crec_vsnprintf(char *str, size_t size, const char *format, va_list args);

#endif /* !HIDE_EC_STDLIB */

#ifdef TEST_BUILD
/**
 * Converts @val to a string written in @buf. The value is converted from
 * least-significant digit to most-significant digit, so the pointer returned
 * does not necessarily point to the start of @buf.
 *
 * This function shouldn't be used directly; it's a helper function for other
 * printf functions and only exposed for testing.
 *
 * @param[out] buf Destination buffer
 * @param[in] buf_len Length of @buf in bytes
 * @param[in] val Value to convert
 * @param[in] precision Fixed point precision; -1 disables fixed point
 * @param[in] base Base
 * @param[in] uppercase true to print hex characters uppercase
 * @return pointer to start of string on success (not necessarily the start of
 * @buf).
 * @return NULL on error
 */
char *uint64_to_str(char *buf, int buf_len, uint64_t val, int precision,
		    int base, bool uppercase);
#endif /* TEST_BUILD */

/**
 * Print timestamp as string to the provided buffer.
 *
 * Guarantees NUL-termination if size != 0.
 *
 * @param[out] str Destination string
 * @param[in] size Size of @str in bytes
 * @param[in] timestamp Timestamp
 * @return Length of string written to @str, not including terminating NUL.
 * @return -EC_ERROR_OVERFLOW when @str buffer is not large enough. @str[0]
 * is set to '\0'.
 * @return -EC_ERROR_INVAL when @size is 0.
 */
int snprintf_timestamp(char *str, size_t size, uint64_t timestamp);

/**
 * Print the current time as a string to the provided buffer.
 *
 * Guarantees NUL-termination if size != 0.
 *
 * @param[out] str Destination string
 * @param[in] size Size of @str in bytes
 * @return Length of string written to @str, not including terminating NUL.
 * @return -EC_ERROR_OVERFLOW when @str buffer is not large enough. @str[0]
 * is set to '\0'.
 * @return -EC_ERROR_INVAL when @size is 0.
 */
int snprintf_timestamp_now(char *str, size_t size);

/**
 * Prints bytes as a hex string in the provided buffer.
 *
 * Guarantees NUL-termination if size != 0.
 *
 * @param[out] str Destination string
 * @param[in] size Size of @str in bytes
 * @param[in] params Data to print
 * @return Length of string written to @str, not including terminating NUL.
 * @return -EC_ERROR_OVERFLOW when @str buffer is not large enough.
 * @return -EC_ERROR_INVAL when @size is 0.
 */
int snprintf_hex_buffer(char *str, size_t size,
			const struct hex_buffer_params *params);

/**
 * @param[in] num_bytes
 * @return number of bytes needed to store @num_bytes as a string (including
 * terminating '\0').
 */
size_t hex_str_buf_size(size_t num_bytes);

#endif /* __CROS_EC_PRINTF_H */