You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a tiny but **fully loaded** printf, sprintf and snprintf implementation.
10
+
This is a tiny but **fully loaded** printf, sprintf and (v)snprintf implementation.
11
11
Primarily designed for usage in embedded systems, where printf is not available due to memory issues or in avoidance of linking against libc.
12
12
Using the standard libc printf may pull **a lot** of unwanted library stuff and can bloat code size about 20k or is not 100% thread safe. In this cases the following implementation can be used.
13
-
Absolutely **NO dependencies** are required, *printf.c* brings all necessary routines, even its own fast `ftoa`, `ntoa` conversion.
13
+
Absolutely **NO dependencies** are required, *printf.c* brings all necessary routines, even its own fast `ftoa` (float), `ntoa` (decimal) conversion.
14
14
15
15
If memory footprint is really a critical issue, floating point and 'long long' support and can be turned off via the `PRINTF_FLOAT_SUPPORT` and `PRINTF_LONG_LONG_SUPPORT` compiler switches.
16
-
When using printf (instead of sprintf) you have to provide your own `_putchar()` low level function as console/serial output.
16
+
When using printf (instead of sprintf/snprintf) you have to provide your own `_putchar()` low level function as console/serial output.
17
17
18
18
19
19
## Highligths and design goals
20
20
21
21
There is a boatload of so called 'tiny' printf implementations around. So why this one?
22
-
I've tested many implementations, but most of them have very limited flag/specifier support, a lot of other dependencies or are just not standard compliant and failing the test suite.
23
-
Therefore I decided to write an own implementation which meets the following items:
22
+
I've tested many implementations, but most of them have very limited flag/specifier support, a lot of other dependencies or are just not standard compliant and failing most of the test suite.
23
+
Therefore I decided to write an own, final implementation which meets the following items:
24
24
25
-
- Very small implementation (< 500 code lines)
25
+
- Very small implementation (around 500 code lines)
26
26
- NO dependencies, no libs, just one module file
27
27
- Support of all important flags, width and precision sub-specifiers (see below)
28
-
- Support of dec/float number representation (with an own fast itoa/ftoa)
28
+
- Support of decimal/floating number representation (with an own fast itoa/ftoa)
@@ -49,10 +49,11 @@ Usage is 1:1 like the according stdio.h library version:
49
49
int printf(const char* format, ...);
50
50
int sprintf(char* buffer, const char* format, ...);
51
51
int snprintf(char* buffer, size_t count, const char* format, ...);
52
+
int vsnprintf(char* buffer, size_t count, const char* format, va_list va);
52
53
```
53
54
54
-
**Due to genaral security reasons it is highly recommended to use `snprintf` (with the max buffer size as `count` parameter) only.**
55
-
`sprintf` has no buffer limitation, so when necessary - use it with care!
55
+
**Due to genaral security reasons it is highly recommended to use `snprintf` (with the max buffer size as `count` parameter) instead of `sprintf`.**
56
+
`sprintf` has no buffer limitation, so when needed - use it really with care!
56
57
57
58
58
59
## Format specifiers
@@ -69,10 +70,9 @@ The following format specifiers are supported:
69
70
| u | Unsigned decimal integer |
70
71
| b | Unsigned binary |
71
72
| o | Unsigned octal |
72
-
| x | Unsigned hexadecimal integer |
73
+
| x | Unsigned hexadecimal integer (lowercase) |
73
74
| X | Unsigned hexadecimal integer (uppercase) |
74
-
| f | Decimal floating point, lowercase |
75
-
| F | Decimal floating point, uppercase |
75
+
| f or F | Decimal floating point |
76
76
| c | Single character |
77
77
| s | String of characters |
78
78
| p | Pointer address |
@@ -90,14 +90,6 @@ The following format specifiers are supported:
90
90
| 0 | Left-pads the number with zeroes (0) instead of spaces when padding is specified (see width sub-specifier). |
91
91
92
92
93
-
### Supported precision
94
-
95
-
| Precision | Description |
96
-
|-----------|-------------|
97
-
| .number | For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0.<br>For f and F specifiers: this is the number of digits to be printed after the decimal point. By default, this is 6, maximum is 9.<br>For s: this is the maximum number of characters to be printed. By default all characters are printed until the ending null character is encountered.<br>If the period is specified without an explicit value for precision, 0 is assumed. |
98
-
| .*| The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted. |
99
-
100
-
101
93
### Supported width
102
94
103
95
| Width | Description |
@@ -106,6 +98,14 @@ The following format specifiers are supported:
106
98
| * | The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted. |
107
99
108
100
101
+
### Supported precision
102
+
103
+
| Precision | Description |
104
+
|-----------|-------------|
105
+
| .number | For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0.<br>For f and F specifiers: this is the number of digits to be printed after the decimal point. By default, this is 6, maximum is 9.<br>For s: this is the maximum number of characters to be printed. By default all characters are printed until the ending null character is encountered.<br>If the period is specified without an explicit value for precision, 0 is assumed. |
106
+
| .*| The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted. |
107
+
108
+
109
109
### Supported length
110
110
111
111
The length sub-specifier modifies the length of the data type.
@@ -114,38 +114,52 @@ The length sub-specifier modifies the length of the data type.
114
114
|--------|------|---------|
115
115
| (none) | int | unsigned int |
116
116
| l | long int | unsigned long int |
117
-
| ll | long long int | unsigned long long int |
117
+
| ll | long long int | unsigned long long int (if PRINTF_LONG_LONG_SUPPORT is defined) |
118
118
| z | size_t int | unsigned size_t int |
119
119
120
120
121
+
### Return value
122
+
Upon successful return, all functions return the number of characters _written_, _excluding_ the null byte used to end the string.
123
+
Functions `snprintf()` and `vsnprintf()` don't write more than `count` bytes, _including_ the terminating null byte ('\0'). If the output was truncated
124
+
due to this limit, the return value is `count`, which indicates any truncation.
125
+
If an output error (invalid buffer etc.) is encountered, `-1` is returned.
126
+
127
+
128
+
## Caveats
129
+
Currently `snprintf()` and `vsnprintf()` don't support `(v)snprintf(nullptr, 0, "Some text")` to get the length of the formatted string only. An error value of `-1` is returned.
130
+
131
+
121
132
## Compiler switches/defines
122
133
123
134
| Name | Default value | Description |
124
135
|------|---------------|-------------|
125
-
| PRINTF_BUFFER_SIZE | 128 | The buffer size used for printf |
126
-
|NTOA_BUFFER_SIZE | 32 | ntoa (integer) conversion buffer size. This must be big enough to hold one converted numeric number, normally 32 is a sufficient value.|
127
-
|FTOA_BUFFER_SIZE | 32 | ftoa (float) conversion buffer size. This must be big enough to hold one converted float number, normally 32 is a sufficient value.|
128
-
| PRINTF_FLOAT_SUPPORT |defined| Define this to enable floating point (%f) support |
129
-
| PRINTF_LONG_LONG_SUPPORT |defined| Define this to enable long long (%ll) support |
136
+
| PRINTF_BUFFER_SIZE | 128 | The buffer size used for the printf() function (not for sprintf/snprintf). Set to 0 if the printf() function is unused (just using sprintf/snprintf)|
137
+
|PRINTF_NTOA_BUFFER_SIZE | 32 | ntoa (integer) conversion buffer size. This must be big enough to hold one converted numeric number_including_ leading zeros, normally 32 is a sufficient value |
138
+
|PRINTF_FTOA_BUFFER_SIZE | 32 | ftoa (float) conversion buffer size. This must be big enough to hold one converted float number_including_ leading zeros, normally 32 is a sufficient value |
139
+
| PRINTF_FLOAT_SUPPORT |undefined| Define this to enable floating point (%f) support |
140
+
| PRINTF_LONG_LONG_SUPPORT |undefined| Define this to enable long long (%ll) support |
130
141
131
142
132
143
## Test suite
133
-
For testing just compile, build and run the test suite located in `test/test_suite.cpp`. This uses the [catch](https://github.com/philsquared/Catch) framework for unit-tests, which is auto-adding main().
144
+
For testing just compile, build and run the test suite located in `test/test_suite.cpp`. This uses the [catch](https://github.com/catchorg/Catch2) framework for unit-tests, which is auto-adding main().
145
+
Running with the `--wait-for-keypress exit` option waits for the enter key after test end.
134
146
135
147
136
148
## Projects using printf
137
-
-[turnkey-board](https://github.com/mpaland/turnkey-board) uses printf as log and generic display formatting/output.
149
+
-[turnkey-board](https://github.com/mpaland/turnkey-board) uses printf as log and generic display formatting/output.
150
+
(Just send me a mail/issue to get your project listed here)
0 commit comments