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