universe@599: /* universe@599: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. universe@599: * universe@599: * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. universe@599: * universe@599: * Redistribution and use in source and binary forms, with or without universe@599: * modification, are permitted provided that the following conditions are met: universe@599: * universe@599: * 1. Redistributions of source code must retain the above copyright universe@599: * notice, this list of conditions and the following disclaimer. universe@599: * universe@599: * 2. Redistributions in binary form must reproduce the above copyright universe@599: * notice, this list of conditions and the following disclaimer in the universe@599: * documentation and/or other materials provided with the distribution. universe@599: * universe@599: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@599: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@599: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@599: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@599: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@599: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@599: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@599: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@599: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@599: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@599: * POSSIBILITY OF SUCH DAMAGE. universe@599: */ universe@599: /** universe@599: * \file printf.h universe@599: * \brief Wrapper for write functions with a printf-like interface. universe@599: * \author Mike Becker universe@599: * \author Olaf Wintermann universe@599: * \copyright 2-Clause BSD License universe@599: */ universe@599: universe@599: #ifndef UCX_PRINTF_H universe@599: #define UCX_PRINTF_H universe@599: universe@599: #include "common.h" universe@599: #include "string.h" universe@599: #include universe@599: universe@599: #ifdef __cplusplus universe@599: extern "C" { universe@599: #endif universe@599: universe@805: universe@805: /** universe@805: * The maximum string length that fits into stack memory. universe@805: */ universe@805: extern unsigned const cx_printf_sbo_size; universe@805: universe@599: /** universe@599: * A \c fprintf like function which writes the output to a stream by universe@599: * using a write_func. universe@599: * universe@599: * @param stream the stream the data is written to universe@599: * @param wfc the write function universe@599: * @param fmt format string universe@599: * @param ... additional arguments universe@599: * @return the total number of bytes written universe@599: */ universe@635: __attribute__((__nonnull__(1, 2, 3), __format__(printf, 3, 4))) universe@635: int cx_fprintf( universe@635: void *stream, universe@635: cx_write_func wfc, universe@635: char const *fmt, universe@635: ... universe@635: ); universe@599: universe@599: /** universe@599: * A \c vfprintf like function which writes the output to a stream by universe@599: * using a write_func. universe@599: * universe@599: * @param stream the stream the data is written to universe@599: * @param wfc the write function universe@599: * @param fmt format string universe@599: * @param ap argument list universe@599: * @return the total number of bytes written universe@599: * @see cx_fprintf() universe@599: */ universe@635: __attribute__((__nonnull__)) universe@635: int cx_vfprintf( universe@635: void *stream, universe@635: cx_write_func wfc, universe@635: char const *fmt, universe@635: va_list ap universe@635: ); universe@599: universe@599: /** universe@599: * A \c asprintf like function which allocates space for a string universe@599: * the result is written to. universe@599: * universe@599: * \note The resulting string is guaranteed to be zero-terminated. universe@599: * universe@599: * @param allocator the CxAllocator used for allocating the string universe@599: * @param fmt format string universe@599: * @param ... additional arguments universe@599: * @return the formatted string universe@599: * @see cx_strfree_a() universe@599: */ universe@635: __attribute__((__nonnull__(1, 2), __format__(printf, 2, 3))) universe@635: cxmutstr cx_asprintf_a( universe@693: CxAllocator const *allocator, universe@635: char const *fmt, universe@635: ... universe@635: ); universe@599: universe@599: /** universe@599: * A \c asprintf like function which allocates space for a string universe@599: * the result is written to. universe@599: * universe@599: * \note The resulting string is guaranteed to be zero-terminated. universe@599: * universe@599: * @param fmt format string universe@599: * @param ... additional arguments universe@599: * @return the formatted string universe@599: * @see cx_strfree() universe@599: */ universe@599: #define cx_asprintf(fmt, ...) \ universe@599: cx_asprintf_a(cxDefaultAllocator, fmt, __VA_ARGS__) universe@599: universe@599: /** universe@599: * A \c vasprintf like function which allocates space for a string universe@599: * the result is written to. universe@599: * universe@599: * \note The resulting string is guaranteed to be zero-terminated. universe@599: * universe@599: * @param allocator the CxAllocator used for allocating the string universe@599: * @param fmt format string universe@599: * @param ap argument list universe@599: * @return the formatted string universe@599: * @see cx_asprintf_a() universe@599: */ universe@635: __attribute__((__nonnull__)) universe@635: cxmutstr cx_vasprintf_a( universe@693: CxAllocator const *allocator, universe@635: char const *fmt, universe@635: va_list ap universe@635: ); universe@599: universe@599: /** universe@599: * A \c vasprintf like function which allocates space for a string universe@599: * the result is written to. universe@599: * universe@599: * \note The resulting string is guaranteed to be zero-terminated. universe@599: * universe@599: * @param fmt format string universe@599: * @param ap argument list universe@599: * @return the formatted string universe@599: * @see cx_asprintf() universe@599: */ universe@599: #define cx_vasprintf(fmt, ap) cx_vasprintf_a(cxDefaultAllocator, fmt, ap) universe@599: universe@599: /** universe@599: * A \c printf like function which writes the output to a CxBuffer. universe@599: * universe@635: * @param buffer a pointer to the buffer the data is written to universe@599: * @param fmt the format string universe@599: * @param ... additional arguments universe@599: * @return the total number of bytes written universe@599: * @see ucx_fprintf() universe@599: */ universe@599: #define cx_bprintf(buffer, fmt, ...) cx_fprintf((CxBuffer*)buffer, \ universe@599: (cx_write_func) cxBufferWrite, fmt, __VA_ARGS__) universe@599: universe@810: universe@810: /** universe@810: * An \c sprintf like function which reallocates the string when the buffer is not large enough. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * @param str a pointer to the string buffer universe@810: * @param len the current length of the buffer universe@810: * @param fmt the format string universe@810: * @param ... additional arguments universe@810: * @return the length of produced string universe@810: */ universe@810: #define cx_sprintf(str, len, fmt, ...) cx_sprintf_a(cxDefaultAllocator, str, len, fmt, __VA_ARGS__) universe@810: universe@810: /** universe@810: * An \c sprintf like function which reallocates the string when the buffer is not large enough. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * \attention The original buffer MUST have been allocated with the same allocator! universe@810: * universe@810: * @param alloc the allocator to use universe@810: * @param str a pointer to the string buffer universe@810: * @param len the current length of the buffer universe@810: * @param fmt the format string universe@810: * @param ... additional arguments universe@810: * @return the length of produced string universe@810: */ universe@810: __attribute__((__nonnull__(1, 2, 4), __format__(printf, 4, 5))) universe@810: int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... ); universe@810: universe@810: universe@810: /** universe@810: * An \c sprintf like function which reallocates the string when the buffer is not large enough. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * @param str a pointer to the string buffer universe@810: * @param len the current length of the buffer universe@810: * @param fmt the format string universe@810: * @param ap argument list universe@810: * @return the length of produced string universe@810: */ universe@810: #define cx_vsprintf(str, len, fmt, ap) cx_vsprintf_a(cxDefaultAllocator, str, len, fmt, ap) universe@810: universe@810: /** universe@810: * An \c sprintf like function which reallocates the string when the buffer is not large enough. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * \attention The original buffer MUST have been allocated with the same allocator! universe@810: * universe@810: * @param alloc the allocator to use universe@810: * @param str a pointer to the string buffer universe@810: * @param len the current length of the buffer universe@810: * @param fmt the format string universe@810: * @param ap argument list universe@810: * @return the length of produced string universe@810: */ universe@810: __attribute__((__nonnull__)) universe@810: int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, va_list ap); universe@810: universe@810: universe@810: /** universe@810: * An \c sprintf like function which allocates a new string when the buffer is not large enough. universe@810: * universe@810: * The location of the resulting string will \em always be stored to \p str. When the buffer universe@810: * was sufficiently large, \p buf itself will be stored to the location of \p str. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * \remark When a new string needed to be allocated, the contents of \p buf will be universe@810: * poisoned after the call, because this function tries to produce the string in \p buf, first. universe@810: * universe@810: * @param buf a pointer to the buffer universe@810: * @param len the length of the buffer universe@810: * @param str a pointer to the location universe@810: * @param fmt the format string universe@810: * @param ... additional arguments universe@810: * @return the length of produced string universe@810: */ universe@810: #define cx_sprintf_s(buf, len, str, fmt, ...) cx_sprintf_sa(cxDefaultAllocator, buf, len, str, fmt, __VA_ARGS__) universe@810: universe@810: /** universe@810: * An \c sprintf like function which allocates a new string when the buffer is not large enough. universe@810: * universe@810: * The location of the resulting string will \em always be stored to \p str. When the buffer universe@810: * was sufficiently large, \p buf itself will be stored to the location of \p str. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * \remark When a new string needed to be allocated, the contents of \p buf will be universe@810: * poisoned after the call, because this function tries to produce the string in \p buf, first. universe@810: * universe@810: * @param alloc the allocator to use universe@810: * @param buf a pointer to the buffer universe@810: * @param len the length of the buffer universe@810: * @param str a pointer to the location universe@810: * @param fmt the format string universe@810: * @param ... additional arguments universe@810: * @return the length of produced string universe@810: */ universe@810: __attribute__((__nonnull__(1, 2, 4, 5), __format__(printf, 5, 6))) universe@810: int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... ); universe@810: universe@810: /** universe@810: * An \c sprintf like function which allocates a new string when the buffer is not large enough. universe@810: * universe@810: * The location of the resulting string will \em always be stored to \p str. When the buffer universe@810: * was sufficiently large, \p buf itself will be stored to the location of \p str. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * \remark When a new string needed to be allocated, the contents of \p buf will be universe@810: * poisoned after the call, because this function tries to produce the string in \p buf, first. universe@810: * universe@810: * @param buf a pointer to the buffer universe@810: * @param len the length of the buffer universe@810: * @param str a pointer to the location universe@810: * @param fmt the format string universe@810: * @param ap argument list universe@810: * @return the length of produced string universe@810: */ universe@810: #define cx_vsprintf_s(buf, len, str, fmt, ap) cx_vsprintf_sa(cxDefaultAllocator, buf, len, str, fmt, ap) universe@810: universe@810: /** universe@810: * An \c sprintf like function which allocates a new string when the buffer is not large enough. universe@810: * universe@810: * The location of the resulting string will \em always be stored to \p str. When the buffer universe@810: * was sufficiently large, \p buf itself will be stored to the location of \p str. universe@810: * universe@810: * \note The resulting string is guaranteed to be zero-terminated. universe@810: * That means, when the buffer needed to be reallocated, the new size of the buffer will be universe@810: * the length returned by this function plus one. universe@810: * universe@810: * \remark When a new string needed to be allocated, the contents of \p buf will be universe@810: * poisoned after the call, because this function tries to produce the string in \p buf, first. universe@810: * universe@810: * @param alloc the allocator to use universe@810: * @param buf a pointer to the buffer universe@810: * @param len the length of the buffer universe@810: * @param str a pointer to the location universe@810: * @param fmt the format string universe@810: * @param ap argument list universe@810: * @return the length of produced string universe@810: */ universe@810: __attribute__((__nonnull__)) universe@810: int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap); universe@810: universe@810: universe@599: #ifdef __cplusplus universe@599: } // extern "C" universe@599: #endif universe@599: universe@599: #endif //UCX_PRINTF_H