UNIXworkcode

1 # Formatting 2 3 In the `printf.h` header you can find various useful `printf()`-like functions that can write the formatted output 4 directly to an arbitrary stream or [buffer](buffer.h.md), or to memory allocated by an [allocator](allocator.h.md). 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, 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 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 13 ## Print to Streams and Buffers 14 15 ```C 16 #include <cx/printf.h> 17 18 int cx_fprintf(void *stream, cx_write_func wfc, 19 const char *fmt, ...); 20 21 int cx_vfprintf(void *stream, cx_write_func wfc, 22 const char *fmt, va_list ap); 23 24 int cx_bprintf(CxBuffer *buf, const char *fmt, ...); 25 ``` 26 27 The `cx_fprintf()` function uses the stdio `snprintf()` to prepare a formatted string 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. 32 33 The `cx_vfprintf()` function is equivalent to `cx_fprintf()`, 34 except that instead of being called with a variable number of arguments, 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. 39 40 ## Print to Freshly Allocated Memory 41 42 ```C 43 #include <cx/printf.h> 44 45 cxmutstr cx_asprintf(const char *fmt, ...); 46 47 cxmutstr cx_asprintf_a(const CxAllocator *allocator, 48 const char *fmt, ...); 49 50 cxmutstr cx_vasprintf(const char *fmt, va_list ap); 51 52 cxmutstr cx_vasprintf_a(const CxAllocator *allocator, 53 const char *fmt, va_list ap); 54 ``` 55 56 The `cx_asprintf()` and `cx_asprintf_a()` functions print the formatted output directly to a freshly allocated 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`. 60 61 The `cx_vasprintf()` and `cx_vasprintf_a()` functions are equivalent to `cx_asprintf()` and `cx_asprintf_a()`, 62 except that instead of being called with a variable number of arguments, 63 they are called with an argument list as defined by `<stdarg.h>`. 64 65 ## Print to Existing Memory 66 67 ```C 68 #include <cx/printf.h> 69 70 int cx_sprintf(char **str, size_t *len, 71 const char *fmt, ...); 72 73 int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, 74 const char *fmt, ...); 75 76 int cx_sprintf_s(char *buf, size_t *len, char **str, 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); 95 ``` 96 97 The `cx_sprintf()` and `cx_sprintf_a()` functions take a pointer `str` to a pointer to a pre-allocated buffer, 98 as well as a pointer `len` to `*str`'s length. 99 If the formatted output does 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. 115 116 The `cx_vsprintf()`, `cx_vsprintf_a()`, `cx_vsprintf_s()`, and `cx_vsprintf_sa()` functions are equivalent 117 to `cx_sprintf()`, `cx_sprintf_a()`, `cx_sprintf_s()`, and `cx_sprintf_sa()`, 118 except that instead of being called with a variable number of arguments, 119 they are called with an argument list as defined by `<stdarg.h>`. 120 121 ## Small Buffer Optimization 122 123 All functions that allocate internal temporary memory use small buffer optimization to avoid a heap allocation 124 if the expected string length is smaller than `cx_printf_sbo_size`. 125 This size cannot be changed at runtime, but modified by defining the `CX_PRINTF_SBO_SIZE` macro when [building](install.md#small-buffer-optimizations) the library. 126 127 <seealso> 128 <category ref="apidoc"> 129 <a href="https://ucx.sourceforge.io/api/printf_8h.html">printf.h</a> 130 </category> 131 </seealso> 132 133