UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 /** 29 * @file printf.h 30 * @brief Wrapper for write-functions with a printf-like interface. 31 * @author Mike Becker 32 * @author Olaf Wintermann 33 * @copyright 2-Clause BSD License 34 */ 35 36 #ifndef UCX_PRINTF_H 37 #define UCX_PRINTF_H 38 39 #include "common.h" 40 #include "string.h" 41 #include <stdarg.h> 42 43 /** 44 * Attribute for printf-like functions. 45 * @param fmt_idx index of the format string parameter 46 * @param arg_idx index of the first formatting argument 47 */ 48 #define cx_attr_printf(fmt_idx, arg_idx) \ 49 __attribute__((__format__(printf, fmt_idx, arg_idx))) 50 51 #ifdef __cplusplus 52 extern "C" { 53 #endif 54 55 56 /** 57 * The maximum string length that fits into stack memory. 58 */ 59 CX_EXPORT extern const unsigned cx_printf_sbo_size; 60 61 /** 62 * A @c fprintf like function which writes the output to a stream by 63 * using a write_func. 64 * 65 * @param stream the stream the data is written to 66 * @param wfc the write function 67 * @param fmt format string 68 * @param ... additional arguments 69 * @return the total number of bytes written or an error code from stdlib printf implementation 70 */ 71 cx_attr_nonnull_arg(1, 2, 3) cx_attr_printf(3, 4) cx_attr_cstr_arg(3) 72 CX_EXPORT int cx_fprintf(void *stream, cx_write_func wfc, const char *fmt, ...); 73 74 /** 75 * A @c vfprintf like function which writes the output to a stream by 76 * using a write_func. 77 * 78 * @param stream the stream the data is written to 79 * @param wfc the write function 80 * @param fmt format string 81 * @param ap argument list 82 * @return the total number of bytes written or an error code from stdlib printf implementation 83 * @see cx_fprintf() 84 */ 85 cx_attr_nonnull cx_attr_cstr_arg(3) 86 CX_EXPORT int cx_vfprintf(void *stream, cx_write_func wfc, const char *fmt, va_list ap); 87 88 /** 89 * An @c asprintf like function which allocates space for a string 90 * the result is written to. 91 * 92 * @note The resulting string is guaranteed to be zero-terminated, 93 * unless there was an error, in which case the string's pointer 94 * will be @c NULL. 95 * 96 * @param allocator the CxAllocator used for allocating the string 97 * @param fmt format string 98 * @param ... additional arguments 99 * @return the formatted string 100 * @see cx_strfree_a() 101 */ 102 cx_attr_nonnull_arg(1, 2) cx_attr_printf(2, 3) cx_attr_cstr_arg(2) 103 CX_EXPORT cxmutstr cx_asprintf_a(const CxAllocator *allocator, const char *fmt, ...); 104 105 /** 106 * An @c asprintf like function which allocates space for a string 107 * the result is written to. 108 * 109 * @note The resulting string is guaranteed to be zero-terminated, 110 * unless there was an error, in which case the string's pointer 111 * will be @c NULL. 112 * 113 * @param fmt (@c char*) format string 114 * @param ... additional arguments 115 * @return (@c cxmutstr) the formatted string 116 * @see cx_strfree() 117 */ 118 #define cx_asprintf(fmt, ...) cx_asprintf_a(cxDefaultAllocator, fmt, __VA_ARGS__) 119 120 /** 121 * A @c vasprintf like function which allocates space for a string 122 * the result is written to. 123 * 124 * @note The resulting string is guaranteed to be zero-terminated, 125 * unless there was an error, in which case the string's pointer 126 * will be @c NULL. 127 * 128 * @param allocator the CxAllocator used for allocating the string 129 * @param fmt format string 130 * @param ap argument list 131 * @return the formatted string 132 * @see cx_asprintf_a() 133 */ 134 cx_attr_nonnull cx_attr_cstr_arg(2) 135 CX_EXPORT cxmutstr cx_vasprintf_a(const CxAllocator *allocator, const char *fmt, va_list ap); 136 137 /** 138 * A @c vasprintf like function which allocates space for a string 139 * the result is written to. 140 * 141 * @note The resulting string is guaranteed to be zero-terminated, 142 * unless there was an error, in which case the string's pointer 143 * will be @c NULL. 144 * 145 * @param fmt (@c char*) format string 146 * @param ap (@c va_list) argument list 147 * @return (@c cxmutstr) the formatted string 148 * @see cx_asprintf() 149 */ 150 #define cx_vasprintf(fmt, ap) cx_vasprintf_a(cxDefaultAllocator, fmt, ap) 151 152 /** 153 * A @c printf like function which writes the output to a CxBuffer. 154 * 155 * @param buffer (@c CxBuffer*) a pointer to the buffer the data is written to 156 * @param fmt (@c char*) the format string 157 * @param ... additional arguments 158 * @return (@c int) the total number of bytes written or an error code from stdlib printf implementation 159 * @see cx_fprintf() 160 * @see cxBufferWrite() 161 */ 162 #define cx_bprintf(buffer, fmt, ...) cx_fprintf((void*)buffer, cxBufferWriteFunc, fmt, __VA_ARGS__) 163 164 165 /** 166 * An @c sprintf like function which reallocates the string when the buffer is not large enough. 167 * 168 * The size of the buffer will be updated in @p len when necessary. 169 * 170 * @note The resulting string, if successful, is guaranteed to be zero-terminated. 171 * 172 * @param str (@c char**) a pointer to the string buffer 173 * @param len (@c size_t*) a pointer to the length of the buffer 174 * @param fmt (@c char*) the format string 175 * @param ... additional arguments 176 * @return (@c int) the length of the produced string or an error code from stdlib printf implementation 177 */ 178 #define cx_sprintf(str, len, fmt, ...) cx_sprintf_a(cxDefaultAllocator, str, len, fmt, __VA_ARGS__) 179 180 /** 181 * An @c sprintf like function which reallocates the string when the buffer is not large enough. 182 * 183 * The size of the buffer will be updated in @p len when necessary. 184 * 185 * @note The resulting string, if successful, is guaranteed to be zero-terminated. 186 * 187 * @attention The original buffer MUST have been allocated with the same allocator! 188 * 189 * @param alloc the allocator to use 190 * @param str a pointer to the string buffer 191 * @param len a pointer to the length of the buffer 192 * @param fmt the format string 193 * @param ... additional arguments 194 * @return the length of the produced string or an error code from stdlib printf implementation 195 */ 196 cx_attr_nonnull_arg(1, 2, 3, 4) cx_attr_printf(4, 5) cx_attr_cstr_arg(4) 197 CX_EXPORT int cx_sprintf_a(const CxAllocator *alloc, char **str, size_t *len, const char *fmt, ...); 198 199 200 /** 201 * An @c sprintf like function which reallocates the string when the buffer is not large enough. 202 * 203 * The size of the buffer will be updated in @p len when necessary. 204 * 205 * @note The resulting string, if successful, is guaranteed to be zero-terminated. 206 * 207 * @param str (@c char**) a pointer to the string buffer 208 * @param len (@c size_t*) a pointer to the length of the buffer 209 * @param fmt (@c char*) the format string 210 * @param ap (@c va_list) argument list 211 * @return (@c int) the length of the produced string or an error code from stdlib printf implementation 212 */ 213 #define cx_vsprintf(str, len, fmt, ap) cx_vsprintf_a(cxDefaultAllocator, str, len, fmt, ap) 214 215 /** 216 * An @c sprintf like function which reallocates the string when the buffer is not large enough. 217 * 218 * The size of the buffer will be updated in @p len when necessary. 219 * 220 * @note The resulting string is guaranteed to be zero-terminated. 221 * 222 * @attention The original buffer MUST have been allocated with the same allocator! 223 * 224 * @param alloc the allocator to use 225 * @param str a pointer to the string buffer 226 * @param len a pointer to the length of the buffer 227 * @param fmt the format string 228 * @param ap argument list 229 * @return the length of the produced string or an error code from stdlib printf implementation 230 */ 231 cx_attr_nonnull cx_attr_cstr_arg(4) cx_attr_access_rw(2) cx_attr_access_rw(3) 232 CX_EXPORT int cx_vsprintf_a(const CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap); 233 234 235 /** 236 * An @c sprintf like function which allocates a new string when the buffer is not large enough. 237 * 238 * The size of the buffer will be updated in @p len when necessary. 239 * 240 * The location of the resulting string will @em always be stored to @p str. When the buffer 241 * was sufficiently large, @p buf itself will be stored to the location of @p str. 242 * 243 * @note The resulting string, if successful, is guaranteed to be zero-terminated. 244 * 245 * @remark When a new string needed to be allocated, the contents of @p buf will be 246 * poisoned after the call, because this function tries to produce the string in @p buf, first. 247 * 248 * @param buf (@c char*) a pointer to the buffer 249 * @param len (@c size_t*) a pointer to the length of the buffer 250 * @param str (@c char**) a pointer where the location of the result shall be stored 251 * @param fmt (@c char*) the format string 252 * @param ... additional arguments 253 * @return (@c int) the length of the produced string or an error code from stdlib printf implementation 254 */ 255 #define cx_sprintf_s(buf, len, str, fmt, ...) cx_sprintf_sa(cxDefaultAllocator, buf, len, str, fmt, __VA_ARGS__) 256 257 /** 258 * An @c sprintf like function which allocates a new string when the buffer is not large enough. 259 * 260 * The size of the buffer will be updated in @p len when necessary. 261 * 262 * The location of the resulting string will @em always be stored to @p str. When the buffer 263 * was sufficiently large, @p buf itself will be stored to the location of @p str. 264 * 265 * @note The resulting string, if successful, is guaranteed to be zero-terminated. 266 * 267 * @remark When a new string needed to be allocated, the contents of @p buf will be 268 * poisoned after the call, because this function tries to produce the string in @p buf, first. 269 * 270 * @param alloc the allocator to use 271 * @param buf a pointer to the buffer 272 * @param len a pointer to the length of the buffer 273 * @param str a pointer where the location of the result shall be stored 274 * @param fmt the format string 275 * @param ... additional arguments 276 * @return the length of the produced string or an error code from stdlib printf implementation 277 */ 278 cx_attr_nonnull_arg(1, 2, 4, 5) cx_attr_printf(5, 6) cx_attr_cstr_arg(5) 279 cx_attr_access_rw(2) cx_attr_access_rw(3) cx_attr_access_rw(4) 280 CX_EXPORT int cx_sprintf_sa(const CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ...); 281 282 /** 283 * An @c sprintf like function which allocates a new string when the buffer is not large enough. 284 * 285 * The size of the buffer will be updated in @p len when necessary. 286 * 287 * The location of the resulting string will @em always be stored to @p str. When the buffer 288 * was sufficiently large, @p buf itself will be stored to the location of @p str. 289 * 290 * @note The resulting string is guaranteed to be zero-terminated. 291 * 292 * @remark When a new string needed to be allocated, the contents of @p buf will be 293 * poisoned after the call, because this function tries to produce the string in @p buf, first. 294 * 295 * @param buf (@c char*) a pointer to the buffer 296 * @param len (@c size_t*) a pointer to the length of the buffer 297 * @param str (@c char**) a pointer where the location of the result shall be stored 298 * @param fmt (@c char*) the format string 299 * @param ap (@c va_list) argument list 300 * @return (@c int) the length of the produced string or an error code from stdlib printf implementation 301 */ 302 #define cx_vsprintf_s(buf, len, str, fmt, ap) cx_vsprintf_sa(cxDefaultAllocator, buf, len, str, fmt, ap) 303 304 /** 305 * An @c sprintf like function which allocates a new string when the buffer is not large enough. 306 * 307 * The size of the buffer will be updated in @p len when necessary. 308 * 309 * The location of the resulting string will @em always be stored to @p str. When the buffer 310 * was sufficiently large, @p buf itself will be stored to the location of @p str. 311 * 312 * @note The resulting string is guaranteed to be zero-terminated. 313 * 314 * @remark When a new string needed to be allocated, the contents of @p buf will be 315 * poisoned after the call, because this function tries to produce the string in @p buf, first. 316 * 317 * @param alloc the allocator to use 318 * @param buf a pointer to the buffer 319 * @param len a pointer to the length of the buffer 320 * @param str a pointer where the location of the result shall be stored 321 * @param fmt the format string 322 * @param ap argument list 323 * @return the length of the produced string or an error code from stdlib printf implementation 324 */ 325 cx_attr_nonnull cx_attr_cstr_arg(5) 326 CX_EXPORT int cx_vsprintf_sa(const CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap); 327 328 329 #ifdef __cplusplus 330 } // extern "C" 331 #endif 332 333 #endif //UCX_PRINTF_H 334