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 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 47 48 /** 49 * The maximum string length that fits into stack memory. 50 */ 51 extern unsigned const cx_printf_sbo_size; 52 53 /** 54 * A \c fprintf like function which writes the output to a stream by 55 * using a write_func. 56 * 57 * @param stream the stream the data is written to 58 * @param wfc the write function 59 * @param fmt format string 60 * @param ... additional arguments 61 * @return the total number of bytes written 62 */ 63 __attribute__((__nonnull__(1, 2, 3), __format__(printf, 3, 4))) 64 int cx_fprintf( 65 void *stream, 66 cx_write_func wfc, 67 char const *fmt, 68 ... 69 ); 70 71 /** 72 * A \c vfprintf like function which writes the output to a stream by 73 * using a write_func. 74 * 75 * @param stream the stream the data is written to 76 * @param wfc the write function 77 * @param fmt format string 78 * @param ap argument list 79 * @return the total number of bytes written 80 * @see cx_fprintf() 81 */ 82 __attribute__((__nonnull__)) 83 int cx_vfprintf( 84 void *stream, 85 cx_write_func wfc, 86 char const *fmt, 87 va_list ap 88 ); 89 90 /** 91 * A \c asprintf like function which allocates space for a string 92 * the result is written to. 93 * 94 * \note The resulting string is guaranteed to be zero-terminated. 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 __attribute__((__nonnull__(1, 2), __format__(printf, 2, 3))) 103 cxmutstr cx_asprintf_a( 104 CxAllocator const *allocator, 105 char const *fmt, 106 ... 107 ); 108 109 /** 110 * A \c asprintf like function which allocates space for a string 111 * the result is written to. 112 * 113 * \note The resulting string is guaranteed to be zero-terminated. 114 * 115 * @param fmt format string 116 * @param ... additional arguments 117 * @return the formatted string 118 * @see cx_strfree() 119 */ 120 #define cx_asprintf(fmt, ...) \ 121 cx_asprintf_a(cxDefaultAllocator, fmt, __VA_ARGS__) 122 123 /** 124 * A \c vasprintf like function which allocates space for a string 125 * the result is written to. 126 * 127 * \note The resulting string is guaranteed to be zero-terminated. 128 * 129 * @param allocator the CxAllocator used for allocating the string 130 * @param fmt format string 131 * @param ap argument list 132 * @return the formatted string 133 * @see cx_asprintf_a() 134 */ 135 __attribute__((__nonnull__)) 136 cxmutstr cx_vasprintf_a( 137 CxAllocator const *allocator, 138 char const *fmt, 139 va_list ap 140 ); 141 142 /** 143 * A \c vasprintf like function which allocates space for a string 144 * the result is written to. 145 * 146 * \note The resulting string is guaranteed to be zero-terminated. 147 * 148 * @param fmt format string 149 * @param ap argument list 150 * @return the formatted string 151 * @see cx_asprintf() 152 */ 153 #define cx_vasprintf(fmt, ap) cx_vasprintf_a(cxDefaultAllocator, fmt, ap) 154 155 /** 156 * A \c printf like function which writes the output to a CxBuffer. 157 * 158 * @param buffer a pointer to the buffer the data is written to 159 * @param fmt the format string 160 * @param ... additional arguments 161 * @return the total number of bytes written 162 * @see ucx_fprintf() 163 */ 164 #define cx_bprintf(buffer, fmt, ...) cx_fprintf((CxBuffer*)buffer, \ 165 (cx_write_func) cxBufferWrite, fmt, __VA_ARGS__) 166 167 168 /** 169 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 170 * 171 * The size of the buffer will be updated in \p len when necessary. 172 * 173 * \note The resulting string is guaranteed to be zero-terminated. 174 * 175 * @param str a pointer to the string buffer 176 * @param len a pointer to the length of the buffer 177 * @param fmt the format string 178 * @param ... additional arguments 179 * @return the length of produced string 180 */ 181 #define cx_sprintf(str, len, fmt, ...) cx_sprintf_a(cxDefaultAllocator, str, len, fmt, __VA_ARGS__) 182 183 /** 184 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 185 * 186 * The size of the buffer will be updated in \p len when necessary. 187 * 188 * \note The resulting string is guaranteed to be zero-terminated. 189 * 190 * \attention The original buffer MUST have been allocated with the same allocator! 191 * 192 * @param alloc the allocator to use 193 * @param str a pointer to the string buffer 194 * @param len a pointer to the length of the buffer 195 * @param fmt the format string 196 * @param ... additional arguments 197 * @return the length of produced string 198 */ 199 __attribute__((__nonnull__(1, 2, 3, 4), __format__(printf, 4, 5))) 200 int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ); 201 202 203 /** 204 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 205 * 206 * The size of the buffer will be updated in \p len when necessary. 207 * 208 * \note The resulting string is guaranteed to be zero-terminated. 209 * 210 * @param str a pointer to the string buffer 211 * @param len a pointer to the length of the buffer 212 * @param fmt the format string 213 * @param ap argument list 214 * @return the length of produced string 215 */ 216 #define cx_vsprintf(str, len, fmt, ap) cx_vsprintf_a(cxDefaultAllocator, str, len, fmt, ap) 217 218 /** 219 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 220 * 221 * The size of the buffer will be updated in \p len when necessary. 222 * 223 * \note The resulting string is guaranteed to be zero-terminated. 224 * 225 * \attention The original buffer MUST have been allocated with the same allocator! 226 * 227 * @param alloc the allocator to use 228 * @param str a pointer to the string buffer 229 * @param len a pointer to the length of the buffer 230 * @param fmt the format string 231 * @param ap argument list 232 * @return the length of produced string 233 */ 234 __attribute__((__nonnull__)) 235 int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap); 236 237 238 /** 239 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 240 * 241 * The size of the buffer will be updated in \p len when necessary. 242 * 243 * The location of the resulting string will \em always be stored to \p str. When the buffer 244 * was sufficiently large, \p buf itself will be stored to the location of \p str. 245 * 246 * \note The resulting string is guaranteed to be zero-terminated. 247 * 248 * \remark When a new string needed to be allocated, the contents of \p buf will be 249 * poisoned after the call, because this function tries to produce the string in \p buf, first. 250 * 251 * @param buf a pointer to the buffer 252 * @param len a pointer to the length of the buffer 253 * @param str a pointer to the location 254 * @param fmt the format string 255 * @param ... additional arguments 256 * @return the length of produced string 257 */ 258 #define cx_sprintf_s(buf, len, str, fmt, ...) cx_sprintf_sa(cxDefaultAllocator, buf, len, str, fmt, __VA_ARGS__) 259 260 /** 261 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 262 * 263 * The size of the buffer will be updated in \p len when necessary. 264 * 265 * The location of the resulting string will \em always be stored to \p str. When the buffer 266 * was sufficiently large, \p buf itself will be stored to the location of \p str. 267 * 268 * \note The resulting string is guaranteed to be zero-terminated. 269 * 270 * \remark When a new string needed to be allocated, the contents of \p buf will be 271 * poisoned after the call, because this function tries to produce the string in \p buf, first. 272 * 273 * @param alloc the allocator to use 274 * @param buf a pointer to the buffer 275 * @param len a pointer to the length of the buffer 276 * @param str a pointer to the location 277 * @param fmt the format string 278 * @param ... additional arguments 279 * @return the length of produced string 280 */ 281 __attribute__((__nonnull__(1, 2, 4, 5), __format__(printf, 5, 6))) 282 int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ); 283 284 /** 285 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 286 * 287 * The size of the buffer will be updated in \p len when necessary. 288 * 289 * The location of the resulting string will \em always be stored to \p str. When the buffer 290 * was sufficiently large, \p buf itself will be stored to the location of \p str. 291 * 292 * \note The resulting string is guaranteed to be zero-terminated. 293 * 294 * \remark When a new string needed to be allocated, the contents of \p buf will be 295 * poisoned after the call, because this function tries to produce the string in \p buf, first. 296 * 297 * @param buf a pointer to the buffer 298 * @param len a pointer to the length of the buffer 299 * @param str a pointer to the location 300 * @param fmt the format string 301 * @param ap argument list 302 * @return the length of produced string 303 */ 304 #define cx_vsprintf_s(buf, len, str, fmt, ap) cx_vsprintf_sa(cxDefaultAllocator, buf, len, str, fmt, ap) 305 306 /** 307 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 308 * 309 * The size of the buffer will be updated in \p len when necessary. 310 * 311 * The location of the resulting string will \em always be stored to \p str. When the buffer 312 * was sufficiently large, \p buf itself will be stored to the location of \p str. 313 * 314 * \note The resulting string is guaranteed to be zero-terminated. 315 * 316 * \remark When a new string needed to be allocated, the contents of \p buf will be 317 * poisoned after the call, because this function tries to produce the string in \p buf, first. 318 * 319 * @param alloc the allocator to use 320 * @param buf a pointer to the buffer 321 * @param len a pointer to the length of the buffer 322 * @param str a pointer to the location 323 * @param fmt the format string 324 * @param ap argument list 325 * @return the length of produced string 326 */ 327 __attribute__((__nonnull__)) 328 int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap); 329 330 331 #ifdef __cplusplus 332 } // extern "C" 333 #endif 334 335 #endif //UCX_PRINTF_H 336