4 directly to an arbitrary stream or [buffer](buffer.h.md), or to memory allocated by an [allocator](allocator.h.md). |
4 directly to an arbitrary stream or [buffer](buffer.h.md), or to memory allocated by an [allocator](allocator.h.md). |
5 |
5 |
6 With the help of these convenience functions, you do not need the libc `snprintf` to print your string to a temporary buffer anymore, |
6 With the help of these convenience functions, you do not need the libc `snprintf` to print your string to a temporary buffer anymore, |
7 plus you do not need to worry about too small buffer sizes, because the functions will automatically allocate enough memory to contain the entire formatted string. |
7 plus you do not need to worry about too small buffer sizes, because the functions will automatically allocate enough memory to contain the entire formatted string. |
8 |
8 |
|
9 > Although UCX usually uses `size_t` for sizes, the return type of all `printf`-like functions |
|
10 > (except for the `cx_asprintf()` family of functions) is `int`, consistent with the stdio `printf` return type. |
|
11 {style="note"} |
|
12 |
9 ## Print to Streams and Buffers |
13 ## Print to Streams and Buffers |
10 |
14 |
11 ```C |
15 ```C |
12 #include <cx/printf.h> |
16 #include <cx/printf.h> |
13 |
17 |
14 int cx_fprintf(void *stream, cx_write_func wfc, |
18 int cx_fprintf(void *stream, cx_write_func wfc, |
15 const char *fmt, ...); |
19 const char *fmt, ...); |
16 |
20 |
17 int cx_vfprintf(void *stream, cx_write_func wfc, |
21 int cx_vfprintf(void *stream, cx_write_func wfc, |
18 const char *fmt, va_list ap); |
22 const char *fmt, va_list ap); |
19 |
23 |
20 int cx_bprintf(CxBuffer *buf, const char *fmt, ...); |
24 int cx_bprintf(CxBuffer *buf, const char *fmt, ...); |
21 ``` |
25 ``` |
22 |
26 |
23 > TODO: document |
27 The `cx_fprintf()` function uses the stdio `snprintf()` to prepare a formatted string |
24 {style="warning"} |
28 which is then written to the `stream` using the write function `wfc`. |
|
29 The return value is the number of bytes written or a value less than zero when an error occurred. |
|
30 If the resulting string is short enough, no additional memory is allocated on the heap. |
|
31 See the Section about [](#small-buffer-optimization) for more details. |
25 |
32 |
26 The `cx_vfprintf()` function is equivalent to `cx_fprintf()`, |
33 The `cx_vfprintf()` function is equivalent to `cx_fprintf()`, |
27 except that instead of being called with a variable number of arguments, |
34 except that instead of being called with a variable number of arguments, |
28 they are called with an argument list as defined by `<stdarg.h>`. |
35 it is called with an argument list as defined by `<stdarg.h>`. |
|
36 |
|
37 The `cx_bprintf()` function is implemented as macro for `cx_fprintf()` with the |
|
38 `CxBuffer` as `stream` and the `cxBufferWriteFunc` as write function. |
29 |
39 |
30 ## Print to Freshly Allocated Memory |
40 ## Print to Freshly Allocated Memory |
31 |
41 |
32 ```C |
42 ```C |
33 #include <cx/printf.h> |
43 #include <cx/printf.h> |
34 |
44 |
35 cxmutstr cx_asprintf(const char *fmt, ...); |
45 cxmutstr cx_asprintf(const char *fmt, ...); |
36 |
46 |
37 cxmutstr cx_asprintf_a(const CxAllocator *allocator, |
47 cxmutstr cx_asprintf_a(const CxAllocator *allocator, |
38 const char *fmt, ...); |
48 const char *fmt, ...); |
39 |
49 |
40 cxmutstr cx_vasprintf(const char *fmt, va_list ap); |
50 cxmutstr cx_vasprintf(const char *fmt, va_list ap); |
41 |
51 |
42 cxmutstr cx_vasprintf_a(const CxAllocator *allocator, |
52 cxmutstr cx_vasprintf_a(const CxAllocator *allocator, |
43 const char *fmt, va_list ap); |
53 const char *fmt, va_list ap); |
44 ``` |
54 ``` |
45 |
55 |
46 > TODO: document |
56 The `cx_asprintf()` and `cx_asprintf_a()` functions print the formatted output directly to a freshly allocated |
47 {style="warning"} |
57 string which is then returned from the function. |
|
58 On platforms (or when using allocators) where allocation can fail, |
|
59 the returned string may be empty and the `ptr` field set to `NULL`. |
48 |
60 |
49 The `cx_vasprintf()` and `cx_vasprintf_a()` functions are equivalent to `cx_asprintf()` and `cx_asprintf_a()`, |
61 The `cx_vasprintf()` and `cx_vasprintf_a()` functions are equivalent to `cx_asprintf()` and `cx_asprintf_a()`, |
50 except that instead of being called with a variable number of arguments, |
62 except that instead of being called with a variable number of arguments, |
51 they are called with an argument list as defined by `<stdarg.h>`. |
63 they are called with an argument list as defined by `<stdarg.h>`. |
52 |
64 |
53 ## Print to Existing Memory |
65 ## Print to Existing Memory |
54 |
66 |
55 ```C |
67 ```C |
56 #include <cx/printf.h> |
68 #include <cx/printf.h> |
57 |
69 |
58 cx_sprintf |
70 int cx_sprintf(char **str, size_t *len, |
59 cx_sprintf_a |
71 const char *fmt, ...); |
60 cx_sprintf_s |
72 |
61 cx_sprintf_sa |
73 int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, |
62 cx_vsprintf |
74 const char *fmt, ...); |
63 cx_vsprintf_a |
75 |
64 cx_vsprintf_s |
76 int cx_sprintf_s(char *buf, size_t *len, char **str, |
65 cx_vsprintf_sa |
77 const char *fmt, ...); |
|
78 |
|
79 int cx_sprintf_sa(CxAllocator *alloc, |
|
80 char *buf, size_t *len, char **str, |
|
81 const char *fmt, ...); |
|
82 |
|
83 int cx_vsprintf(char **str, size_t *len, |
|
84 const char *fmt, va_list ap); |
|
85 |
|
86 int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, |
|
87 const char *fmt, va_list ap); |
|
88 |
|
89 int cx_vsprintf_s(char *buf, size_t *len, char **str, |
|
90 const char *fmt, ...); |
|
91 |
|
92 int cx_vsprintf_sa(CxAllocator *alloc, |
|
93 char *buf, size_t *len, char **str, |
|
94 const char *fmt, va_list ap); |
66 ``` |
95 ``` |
67 |
96 |
68 > TODO: document |
97 The `cx_sprintf()` and `cx_sprintf_a()` functions take a pointer `str` to a pointer to a pre-allocated buffer, |
69 {style="warning"} |
98 as well as a pointer `len` to `*str`'s length. |
|
99 If the formatted output would not fit into this buffer, it is reallocated |
|
100 and the new pointer to the buffer and the new length are written back to the variables pointed to by `str` and `len`. |
|
101 |
|
102 The `cx_sprintf_s()` and `cx_sprintf_sa()` functions differ from the previous function in that they take |
|
103 the pointer to the pre-allocated buffer in the `buf` argument and not in the `str` argument |
|
104 (which in this case is only used for storing the resulting pointer), and _always_ allocate an entirely new buffer |
|
105 when the length is insufficient. |
|
106 This is particularly useful when you want to print the formatted string to a buffer allocated on the stack, but also |
|
107 want the option to switch to heap-allocated memory when necessary. |
|
108 |
|
109 In other words: when the formatted output fits into the buffer pointed to by `buf`, `buf` will be written to `*str`. |
|
110 Otherwise, the pointer to the freshly allocated buffer is written to `*str`. |
|
111 |
|
112 > When using `cx_sprintf()` or `cx_sprintf_a()` you should always make sure that the string pointed to by `*str` |
|
113 > was allocated by a matching allocator. |
|
114 > This restriction does not apply for `cx_sprintf_s()` or `cx_sprintf_sa()` which would allocate a fresh buffer when needed. |
70 |
115 |
71 The `cx_vsprintf()`, `cx_vsprintf_a()`, `cx_vsprintf_s()`, and `cx_vsprintf_sa()` functions are equivalent |
116 The `cx_vsprintf()`, `cx_vsprintf_a()`, `cx_vsprintf_s()`, and `cx_vsprintf_sa()` functions are equivalent |
72 to `cx_sprintf()`, `cx_sprintf_a()`, `cx_sprintf_s()`, and `cx_sprintf_sa()`, |
117 to `cx_sprintf()`, `cx_sprintf_a()`, `cx_sprintf_s()`, and `cx_sprintf_sa()`, |
73 except that instead of being called with a variable number of arguments, |
118 except that instead of being called with a variable number of arguments, |
74 they are called with an argument list as defined by `<stdarg.h>`. |
119 they are called with an argument list as defined by `<stdarg.h>`. |