diff -r eb48f716b31c -r e10457d74fe1 src/ucx/cx/printf.h --- a/src/ucx/cx/printf.h Mon Feb 10 17:44:51 2025 +0100 +++ b/src/ucx/cx/printf.h Sun Mar 02 18:10:52 2025 +0100 @@ -26,12 +26,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ /** - * \file printf.h - * \brief Wrapper for write functions with a printf-like interface. - * \author Mike Becker - * \author Olaf Wintermann - * \version 3.0 - * \copyright 2-Clause BSD License + * @file printf.h + * @brief Wrapper for write functions with a printf-like interface. + * @author Mike Becker + * @author Olaf Wintermann + * @copyright 2-Clause BSD License */ #ifndef UCX_PRINTF_H @@ -41,52 +40,74 @@ #include "string.h" #include <stdarg.h> +/** + * Attribute for printf-like functions. + * @param fmt_idx index of the format string parameter + * @param arg_idx index of the first formatting argument + */ +#define cx_attr_printf(fmt_idx, arg_idx) \ + __attribute__((__format__(printf, fmt_idx, arg_idx))) + #ifdef __cplusplus extern "C" { #endif + /** - * A \c fprintf like function which writes the output to a stream by + * The maximum string length that fits into stack memory. + */ +cx_attr_export +extern const unsigned cx_printf_sbo_size; + +/** + * A @c fprintf like function which writes the output to a stream by * using a write_func. * * @param stream the stream the data is written to * @param wfc the write function * @param fmt format string * @param ... additional arguments - * @return the total number of bytes written + * @return the total number of bytes written or an error code from stdlib printf implementation */ -__attribute__((__nonnull__(1, 2, 3), __format__(printf, 3, 4))) +cx_attr_nonnull_arg(1, 2, 3) +cx_attr_printf(3, 4) +cx_attr_cstr_arg(3) +cx_attr_export int cx_fprintf( void *stream, cx_write_func wfc, - char const *fmt, + const char *fmt, ... ); /** - * A \c vfprintf like function which writes the output to a stream by + * A @c vfprintf like function which writes the output to a stream by * using a write_func. * * @param stream the stream the data is written to * @param wfc the write function * @param fmt format string * @param ap argument list - * @return the total number of bytes written + * @return the total number of bytes written or an error code from stdlib printf implementation * @see cx_fprintf() */ -__attribute__((__nonnull__)) +cx_attr_nonnull +cx_attr_cstr_arg(3) +cx_attr_export int cx_vfprintf( void *stream, cx_write_func wfc, - char const *fmt, + const char *fmt, va_list ap ); /** - * A \c asprintf like function which allocates space for a string + * A @c asprintf like function which allocates space for a string * the result is written to. * - * \note The resulting string is guaranteed to be zero-terminated. + * @note The resulting string is guaranteed to be zero-terminated, + * unless there was an error, in which case the string's pointer + * will be @c NULL. * * @param allocator the CxAllocator used for allocating the string * @param fmt format string @@ -94,32 +115,39 @@ * @return the formatted string * @see cx_strfree_a() */ -__attribute__((__nonnull__(1, 2), __format__(printf, 2, 3))) +cx_attr_nonnull_arg(1, 2) +cx_attr_printf(2, 3) +cx_attr_cstr_arg(2) +cx_attr_export cxmutstr cx_asprintf_a( - CxAllocator const *allocator, - char const *fmt, + const CxAllocator *allocator, + const char *fmt, ... ); /** - * A \c asprintf like function which allocates space for a string + * A @c asprintf like function which allocates space for a string * the result is written to. * - * \note The resulting string is guaranteed to be zero-terminated. + * @note The resulting string is guaranteed to be zero-terminated, + * unless there was an error, in which case the string's pointer + * will be @c NULL. * - * @param fmt format string + * @param fmt (@c char*) format string * @param ... additional arguments - * @return the formatted string + * @return (@c cxmutstr) the formatted string * @see cx_strfree() */ #define cx_asprintf(fmt, ...) \ cx_asprintf_a(cxDefaultAllocator, fmt, __VA_ARGS__) /** -* A \c vasprintf like function which allocates space for a string +* A @c vasprintf like function which allocates space for a string * the result is written to. * - * \note The resulting string is guaranteed to be zero-terminated. + * @note The resulting string is guaranteed to be zero-terminated, + * unless there was an error, in which case the string's pointer + * will be @c NULL. * * @param allocator the CxAllocator used for allocating the string * @param fmt format string @@ -127,37 +155,247 @@ * @return the formatted string * @see cx_asprintf_a() */ -__attribute__((__nonnull__)) +cx_attr_nonnull +cx_attr_cstr_arg(2) +cx_attr_export cxmutstr cx_vasprintf_a( - CxAllocator const *allocator, - char const *fmt, + const CxAllocator *allocator, + const char *fmt, va_list ap ); /** -* A \c vasprintf like function which allocates space for a string +* A @c vasprintf like function which allocates space for a string * the result is written to. * - * \note The resulting string is guaranteed to be zero-terminated. + * @note The resulting string is guaranteed to be zero-terminated, + * unless there was in error, in which case the string's pointer + * will be @c NULL. * - * @param fmt format string - * @param ap argument list - * @return the formatted string + * @param fmt (@c char*) format string + * @param ap (@c va_list) argument list + * @return (@c cxmutstr) the formatted string * @see cx_asprintf() */ #define cx_vasprintf(fmt, ap) cx_vasprintf_a(cxDefaultAllocator, fmt, ap) /** - * A \c printf like function which writes the output to a CxBuffer. + * A @c printf like function which writes the output to a CxBuffer. + * + * @param buffer (@c CxBuffer*) a pointer to the buffer the data is written to + * @param fmt (@c char*) the format string + * @param ... additional arguments + * @return (@c int) the total number of bytes written or an error code from stdlib printf implementation + * @see cx_fprintf() + * @see cxBufferWrite() + */ +#define cx_bprintf(buffer, fmt, ...) cx_fprintf((void*)buffer, \ + cxBufferWriteFunc, fmt, __VA_ARGS__) + + +/** + * An @c sprintf like function which reallocates the string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * @note The resulting string, if successful, is guaranteed to be zero-terminated. * - * @param buffer a pointer to the buffer the data is written to + * @param str (@c char**) a pointer to the string buffer + * @param len (@c size_t*) a pointer to the length of the buffer + * @param fmt (@c char*) the format string + * @param ... additional arguments + * @return (@c int) the length of produced string or an error code from stdlib printf implementation + */ +#define cx_sprintf(str, len, fmt, ...) cx_sprintf_a(cxDefaultAllocator, str, len, fmt, __VA_ARGS__) + +/** + * An @c sprintf like function which reallocates the string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * @note The resulting string, if successful, is guaranteed to be zero-terminated. + * + * @attention The original buffer MUST have been allocated with the same allocator! + * + * @param alloc the allocator to use + * @param str a pointer to the string buffer + * @param len a pointer to the length of the buffer * @param fmt the format string * @param ... additional arguments - * @return the total number of bytes written - * @see ucx_fprintf() + * @return the length of produced string or an error code from stdlib printf implementation + */ +cx_attr_nonnull_arg(1, 2, 3, 4) +cx_attr_printf(4, 5) +cx_attr_cstr_arg(4) +cx_attr_export +int cx_sprintf_a( + CxAllocator *alloc, + char **str, + size_t *len, + const char *fmt, + ... +); + + +/** + * An @c sprintf like function which reallocates the string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * @note The resulting string, if successful, is guaranteed to be zero-terminated. + * + * @param str (@c char**) a pointer to the string buffer + * @param len (@c size_t*) a pointer to the length of the buffer + * @param fmt (@c char*) the format string + * @param ap (@c va_list) argument list + * @return (@c int) the length of produced string or an error code from stdlib printf implementation + */ +#define cx_vsprintf(str, len, fmt, ap) cx_vsprintf_a(cxDefaultAllocator, str, len, fmt, ap) + +/** + * An @c sprintf like function which reallocates the string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * @note The resulting string is guaranteed to be zero-terminated. + * + * @attention The original buffer MUST have been allocated with the same allocator! + * + * @param alloc the allocator to use + * @param str a pointer to the string buffer + * @param len a pointer to the length of the buffer + * @param fmt the format string + * @param ap argument list + * @return the length of produced string or an error code from stdlib printf implementation + */ +cx_attr_nonnull +cx_attr_cstr_arg(4) +cx_attr_access_rw(2) +cx_attr_access_rw(3) +cx_attr_export +int cx_vsprintf_a( + CxAllocator *alloc, + char **str, + size_t *len, + const char *fmt, + va_list ap +); + + +/** + * An @c sprintf like function which allocates a new string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * The location of the resulting string will @em always be stored to @p str. When the buffer + * was sufficiently large, @p buf itself will be stored to the location of @p str. + * + * @note The resulting string, if successful, is guaranteed to be zero-terminated. + * + * @remark When a new string needed to be allocated, the contents of @p buf will be + * poisoned after the call, because this function tries to produce the string in @p buf, first. + * + * @param buf (@c char*) a pointer to the buffer + * @param len (@c size_t*) a pointer to the length of the buffer + * @param str (@c char**) a pointer where the location of the result shall be stored + * @param fmt (@c char*) the format string + * @param ... additional arguments + * @return (@c int) the length of produced string or an error code from stdlib printf implementation */ -#define cx_bprintf(buffer, fmt, ...) cx_fprintf((CxBuffer*)buffer, \ - (cx_write_func) cxBufferWrite, fmt, __VA_ARGS__) +#define cx_sprintf_s(buf, len, str, fmt, ...) cx_sprintf_sa(cxDefaultAllocator, buf, len, str, fmt, __VA_ARGS__) + +/** + * An @c sprintf like function which allocates a new string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * The location of the resulting string will @em always be stored to @p str. When the buffer + * was sufficiently large, @p buf itself will be stored to the location of @p str. + * + * @note The resulting string, if successful, is guaranteed to be zero-terminated. + * + * @remark When a new string needed to be allocated, the contents of @p buf will be + * poisoned after the call, because this function tries to produce the string in @p buf, first. + * + * @param alloc the allocator to use + * @param buf a pointer to the buffer + * @param len a pointer to the length of the buffer + * @param str a pointer where the location of the result shall be stored + * @param fmt the format string + * @param ... additional arguments + * @return the length of produced string or an error code from stdlib printf implementation + */ +cx_attr_nonnull_arg(1, 2, 4, 5) +cx_attr_printf(5, 6) +cx_attr_cstr_arg(5) +cx_attr_access_rw(2) +cx_attr_access_rw(3) +cx_attr_access_rw(4) +cx_attr_export +int cx_sprintf_sa( + CxAllocator *alloc, + char *buf, + size_t *len, + char **str, + const char *fmt, + ... +); + +/** + * An @c sprintf like function which allocates a new string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * The location of the resulting string will @em always be stored to @p str. When the buffer + * was sufficiently large, @p buf itself will be stored to the location of @p str. + * + * @note The resulting string is guaranteed to be zero-terminated. + * + * @remark When a new string needed to be allocated, the contents of @p buf will be + * poisoned after the call, because this function tries to produce the string in @p buf, first. + * + * @param buf (@c char*) a pointer to the buffer + * @param len (@c size_t*) a pointer to the length of the buffer + * @param str (@c char**) a pointer where the location of the result shall be stored + * @param fmt (@c char*) the format string + * @param ap (@c va_list) argument list + * @return (@c int) the length of produced string or an error code from stdlib printf implementation + */ +#define cx_vsprintf_s(buf, len, str, fmt, ap) cx_vsprintf_sa(cxDefaultAllocator, buf, len, str, fmt, ap) + +/** + * An @c sprintf like function which allocates a new string when the buffer is not large enough. + * + * The size of the buffer will be updated in @p len when necessary. + * + * The location of the resulting string will @em always be stored to @p str. When the buffer + * was sufficiently large, @p buf itself will be stored to the location of @p str. + * + * @note The resulting string is guaranteed to be zero-terminated. + * + * @remark When a new string needed to be allocated, the contents of @p buf will be + * poisoned after the call, because this function tries to produce the string in @p buf, first. + * + * @param alloc the allocator to use + * @param buf a pointer to the buffer + * @param len a pointer to the length of the buffer + * @param str a pointer where the location of the result shall be stored + * @param fmt the format string + * @param ap argument list + * @return the length of produced string or an error code from stdlib printf implementation + */ +cx_attr_nonnull +cx_attr_cstr_arg(5) +cx_attr_export +int cx_vsprintf_sa( + CxAllocator *alloc, + char *buf, + size_t *len, + char **str, + const char *fmt, + va_list ap +); + #ifdef __cplusplus } // extern "C"