src/printf.c

Fri, 12 Apr 2024 21:48:12 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 12 Apr 2024 21:48:12 +0200
changeset 849
edb9f875b7f9
parent 813
aba6d37b78bd
permissions
-rw-r--r--

improves interface of cx_sprintf() variants

universe@599 1 /*
universe@599 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@599 3 *
universe@599 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
universe@599 5 *
universe@599 6 * Redistribution and use in source and binary forms, with or without
universe@599 7 * modification, are permitted provided that the following conditions are met:
universe@599 8 *
universe@599 9 * 1. Redistributions of source code must retain the above copyright
universe@599 10 * notice, this list of conditions and the following disclaimer.
universe@599 11 *
universe@599 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@599 13 * notice, this list of conditions and the following disclaimer in the
universe@599 14 * documentation and/or other materials provided with the distribution.
universe@599 15 *
universe@599 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@599 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@599 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@599 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@599 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@599 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@599 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@599 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@599 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@599 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@599 26 * POSSIBILITY OF SUCH DAMAGE.
universe@599 27 */
universe@599 28
universe@599 29 #include "cx/printf.h"
universe@599 30
universe@599 31 #include <stdio.h>
universe@599 32 #include <string.h>
universe@599 33
universe@643 34 #ifndef CX_PRINTF_SBO_SIZE
universe@643 35 #define CX_PRINTF_SBO_SIZE 512
universe@643 36 #endif
universe@805 37 unsigned const cx_printf_sbo_size = CX_PRINTF_SBO_SIZE;
universe@599 38
universe@643 39 int cx_fprintf(
universe@643 40 void *stream,
universe@643 41 cx_write_func wfc,
universe@643 42 char const *fmt,
universe@643 43 ...
universe@643 44 ) {
universe@599 45 int ret;
universe@599 46 va_list ap;
universe@599 47 va_start(ap, fmt);
universe@599 48 ret = cx_vfprintf(stream, wfc, fmt, ap);
universe@599 49 va_end(ap);
universe@599 50 return ret;
universe@599 51 }
universe@599 52
universe@644 53 int cx_vfprintf(
universe@644 54 void *stream,
universe@644 55 cx_write_func wfc,
universe@644 56 char const *fmt,
universe@644 57 va_list ap
universe@644 58 ) {
universe@643 59 char buf[CX_PRINTF_SBO_SIZE];
universe@599 60 va_list ap2;
universe@599 61 va_copy(ap2, ap);
universe@643 62 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap);
universe@599 63 if (ret < 0) {
universe@811 64 va_end(ap2);
universe@599 65 return ret;
universe@643 66 } else if (ret < CX_PRINTF_SBO_SIZE) {
universe@811 67 va_end(ap2);
universe@599 68 return (int) wfc(buf, 1, ret, stream);
universe@599 69 } else {
universe@599 70 int len = ret + 1;
universe@599 71 char *newbuf = malloc(len);
universe@599 72 if (!newbuf) {
universe@811 73 va_end(ap2);
universe@599 74 return -1;
universe@599 75 }
universe@599 76
universe@599 77 ret = vsnprintf(newbuf, len, fmt, ap2);
universe@811 78 va_end(ap2);
universe@599 79 if (ret > 0) {
universe@599 80 ret = (int) wfc(newbuf, 1, ret, stream);
universe@599 81 }
universe@599 82 free(newbuf);
universe@599 83 }
universe@599 84 return ret;
universe@599 85 }
universe@599 86
universe@644 87 cxmutstr cx_asprintf_a(
universe@693 88 CxAllocator const *allocator,
universe@644 89 char const *fmt,
universe@644 90 ...
universe@644 91 ) {
universe@599 92 va_list ap;
universe@599 93 va_start(ap, fmt);
universe@805 94 cxmutstr ret = cx_vasprintf_a(allocator, fmt, ap);
universe@599 95 va_end(ap);
universe@599 96 return ret;
universe@599 97 }
universe@599 98
universe@644 99 cxmutstr cx_vasprintf_a(
universe@693 100 CxAllocator const *a,
universe@644 101 char const *fmt,
universe@644 102 va_list ap
universe@644 103 ) {
universe@599 104 cxmutstr s;
universe@599 105 s.ptr = NULL;
universe@599 106 s.length = 0;
universe@643 107 char buf[CX_PRINTF_SBO_SIZE];
universe@599 108 va_list ap2;
universe@599 109 va_copy(ap2, ap);
universe@643 110 int ret = vsnprintf(buf, CX_PRINTF_SBO_SIZE, fmt, ap);
universe@812 111 if (ret >= 0 && ret < CX_PRINTF_SBO_SIZE) {
universe@599 112 s.ptr = cxMalloc(a, ret + 1);
universe@599 113 if (s.ptr) {
universe@599 114 s.length = (size_t) ret;
universe@599 115 memcpy(s.ptr, buf, ret);
universe@599 116 s.ptr[s.length] = '\0';
universe@599 117 }
universe@599 118 } else {
universe@599 119 int len = ret + 1;
universe@599 120 s.ptr = cxMalloc(a, len);
universe@599 121 if (s.ptr) {
universe@599 122 ret = vsnprintf(s.ptr, len, fmt, ap2);
universe@599 123 if (ret < 0) {
universe@599 124 free(s.ptr);
universe@599 125 s.ptr = NULL;
universe@599 126 } else {
universe@599 127 s.length = (size_t) ret;
universe@599 128 }
universe@599 129 }
universe@599 130 }
universe@811 131 va_end(ap2);
universe@599 132 return s;
universe@599 133 }
universe@599 134
universe@849 135 int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ) {
universe@810 136 va_list ap;
universe@810 137 va_start(ap, fmt);
universe@810 138 int ret = cx_vsprintf_a(alloc, str, len, fmt, ap);
universe@810 139 va_end(ap);
universe@810 140 return ret;
universe@810 141 }
universe@810 142
universe@849 143 int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap) {
universe@810 144 va_list ap2;
universe@810 145 va_copy(ap2, ap);
universe@849 146 int ret = vsnprintf(*str, *len, fmt, ap);
universe@849 147 if ((unsigned) ret >= *len) {
universe@810 148 unsigned newlen = ret + 1;
universe@810 149 char *ptr = cxRealloc(alloc, *str, newlen);
universe@810 150 if (ptr) {
universe@810 151 int newret = vsnprintf(ptr, newlen, fmt, ap2);
universe@810 152 if (newret < 0) {
universe@810 153 cxFree(alloc, ptr);
universe@810 154 } else {
universe@849 155 *len = newlen;
universe@810 156 *str = ptr;
universe@813 157 ret = newret;
universe@810 158 }
universe@810 159 }
universe@810 160 }
universe@813 161 va_end(ap2);
universe@813 162 return ret;
universe@810 163 }
universe@810 164
universe@849 165 int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ) {
universe@810 166 va_list ap;
universe@810 167 va_start(ap, fmt);
universe@810 168 int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap);
universe@810 169 va_end(ap);
universe@810 170 return ret;
universe@810 171 }
universe@810 172
universe@849 173 int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap) {
universe@810 174 va_list ap2;
universe@810 175 va_copy(ap2, ap);
universe@849 176 int ret = vsnprintf(buf, *len, fmt, ap);
universe@810 177 *str = buf;
universe@849 178 if ((unsigned) ret >= *len) {
universe@810 179 unsigned newlen = ret + 1;
universe@810 180 char *ptr = cxMalloc(alloc, newlen);
universe@810 181 if (ptr) {
universe@810 182 int newret = vsnprintf(ptr, newlen, fmt, ap2);
universe@810 183 if (newret < 0) {
universe@810 184 cxFree(alloc, ptr);
universe@810 185 } else {
universe@849 186 *len = newlen;
universe@810 187 *str = ptr;
universe@813 188 ret = newret;
universe@810 189 }
universe@810 190 }
universe@810 191 }
universe@813 192 va_end(ap2);
universe@813 193 return ret;
universe@810 194 }

mercurial