src/cx/printf.h

Tue, 16 Jan 2024 23:13:01 +0100

author
Mike Becker <universe@uap-core.de>
date
Tue, 16 Jan 2024 23:13:01 +0100
changeset 810
85859399a0cc
parent 805
26500fc24058
child 849
edb9f875b7f9
permissions
-rw-r--r--

add cx_sprintf() variants - fixes #353

     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  */
    36 #ifndef UCX_PRINTF_H
    37 #define UCX_PRINTF_H
    39 #include "common.h"
    40 #include "string.h"
    41 #include <stdarg.h>
    43 #ifdef __cplusplus
    44 extern "C" {
    45 #endif
    48 /**
    49  * The maximum string length that fits into stack memory.
    50  */
    51 extern unsigned const cx_printf_sbo_size;
    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 );
    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 );
    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 );
   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__)
   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 );
   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)
   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__)
   168 /**
   169  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
   170  *
   171  * \note The resulting string is guaranteed to be zero-terminated.
   172  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   173  * the length returned by this function plus one.
   174  *
   175  * @param str a pointer to the string buffer
   176  * @param len the current 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__)
   183 /**
   184  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
   185  *
   186  * \note The resulting string is guaranteed to be zero-terminated.
   187  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   188  * the length returned by this function plus one.
   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 the current 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, 4), __format__(printf, 4, 5)))
   200 int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... );
   203 /**
   204  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
   205  *
   206  * \note The resulting string is guaranteed to be zero-terminated.
   207  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   208  * the length returned by this function plus one.
   209  *
   210  * @param str a pointer to the string buffer
   211  * @param len the current 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)
   218 /**
   219  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
   220  *
   221  * \note The resulting string is guaranteed to be zero-terminated.
   222  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   223  * the length returned by this function plus one.
   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 the current 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);
   238 /**
   239  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
   240  *
   241  * The location of the resulting string will \em always be stored to \p str. When the buffer
   242  * was sufficiently large, \p buf itself will be stored to the location of \p str.
   243  *
   244  * \note The resulting string is guaranteed to be zero-terminated.
   245  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   246  * the length returned by this function plus one.
   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 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__)
   260 /**
   261  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
   262  *
   263  * The location of the resulting string will \em always be stored to \p str. When the buffer
   264  * was sufficiently large, \p buf itself will be stored to the location of \p str.
   265  *
   266  * \note The resulting string is guaranteed to be zero-terminated.
   267  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   268  * the length returned by this function plus one.
   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 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, ... );
   284 /**
   285  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
   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  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   292  * the length returned by this function plus one.
   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 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)
   306 /**
   307  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
   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  * That means, when the buffer needed to be reallocated, the new size of the buffer will be
   314  * the length returned by this function plus one.
   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 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);
   331 #ifdef __cplusplus
   332 } // extern "C"
   333 #endif
   335 #endif //UCX_PRINTF_H

mercurial