Sat, 05 Nov 2022 17:17:17 +0100
#222 add printf-like functions
src/CMakeLists.txt | file | annotate | diff | comparison | revisions | |
src/cx/printf.h | file | annotate | diff | comparison | revisions | |
src/printf.c | file | annotate | diff | comparison | revisions |
--- a/src/CMakeLists.txt Sun Oct 23 17:02:07 2022 +0200 +++ b/src/CMakeLists.txt Sat Nov 05 17:17:17 2022 +0100 @@ -9,6 +9,7 @@ hash_key.c hash_map.c basic_mempool.c + printf.c ) set(headers cx/common.h @@ -25,6 +26,7 @@ cx/hash_map.h cx/mempool.h cx/basic_mempool.h + cx/printf.h ) add_library(ucx SHARED ${sources})
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cx/printf.h Sat Nov 05 17:17:17 2022 +0100 @@ -0,0 +1,144 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * 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 + */ + +#ifndef UCX_PRINTF_H +#define UCX_PRINTF_H + +#include "common.h" +#include "string.h" +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 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 + */ +int cx_fprintf(void *stream, cx_write_func wfc, char const *fmt, ...); + +/** + * 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 + * @see cx_fprintf() + */ +int cx_vfprintf(void *stream, cx_write_func wfc, char const *fmt, va_list ap); + +/** + * 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. + * + * @param allocator the CxAllocator used for allocating the string + * @param fmt format string + * @param ... additional arguments + * @return the formatted string + * @see cx_strfree_a() + */ +cxmutstr cx_asprintf_a(CxAllocator *allocator, char const *fmt, ...); + +/** + * 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. + * + * @param fmt format string + * @param ... additional arguments + * @return 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 + * the result is written to. + * + * \note The resulting string is guaranteed to be zero-terminated. + * + * @param allocator the CxAllocator used for allocating the string + * @param fmt format string + * @param ap argument list + * @return the formatted string + * @see cx_asprintf_a() + */ +cxmutstr cx_vasprintf_a(CxAllocator *allocator, char const *fmt, va_list ap); + +/** +* 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. + * + * @param fmt format string + * @param ap argument list + * @return 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. + * + * @param buffer the buffer the data is written to + * @param fmt the format string + * @param ... additional arguments + * @return the total number of bytes written + * @see ucx_fprintf() + */ +#define cx_bprintf(buffer, fmt, ...) cx_fprintf((CxBuffer*)buffer, \ + (cx_write_func) cxBufferWrite, fmt, __VA_ARGS__) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //UCX_PRINTF_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/printf.c Sat Nov 05 17:17:17 2022 +0100 @@ -0,0 +1,109 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "cx/printf.h" + +#include <stdio.h> +#include <string.h> + +#define UCX_PRINTF_BUFSIZE 256 + +int cx_fprintf(void *stream, cx_write_func wfc, const char *fmt, ...) { + int ret; + va_list ap; + va_start(ap, fmt); + ret = cx_vfprintf(stream, wfc, fmt, ap); + va_end(ap); + return ret; +} + +int cx_vfprintf(void *stream, cx_write_func wfc, const char *fmt, va_list ap) { + char buf[UCX_PRINTF_BUFSIZE]; + va_list ap2; + va_copy(ap2, ap); + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); + if (ret < 0) { + return ret; + } else if (ret < UCX_PRINTF_BUFSIZE) { + return (int) wfc(buf, 1, ret, stream); + } else { + int len = ret + 1; + char *newbuf = malloc(len); + if (!newbuf) { + return -1; + } + + ret = vsnprintf(newbuf, len, fmt, ap2); + if (ret > 0) { + ret = (int) wfc(newbuf, 1, ret, stream); + } + free(newbuf); + } + return ret; +} + +cxmutstr cx_asprintf_a(CxAllocator *allocator, const char *fmt, ...) { + va_list ap; + cxmutstr ret; + va_start(ap, fmt); + ret = cx_vasprintf_a(allocator, fmt, ap); + va_end(ap); + return ret; +} + +cxmutstr cx_vasprintf_a(CxAllocator *a, const char *fmt, va_list ap) { + cxmutstr s; + s.ptr = NULL; + s.length = 0; + char buf[UCX_PRINTF_BUFSIZE]; + va_list ap2; + va_copy(ap2, ap); + int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap); + if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) { + s.ptr = cxMalloc(a, ret + 1); + if (s.ptr) { + s.length = (size_t) ret; + memcpy(s.ptr, buf, ret); + s.ptr[s.length] = '\0'; + } + } else { + int len = ret + 1; + s.ptr = cxMalloc(a, len); + if (s.ptr) { + ret = vsnprintf(s.ptr, len, fmt, ap2); + if (ret < 0) { + free(s.ptr); + s.ptr = NULL; + } else { + s.length = (size_t) ret; + } + } + } + return s; +} +