Branch data Line data Source code
1 : : /*
2 : : * This file is part of libplacebo.
3 : : *
4 : : * libplacebo is free software; you can redistribute it and/or
5 : : * modify it under the terms of the GNU Lesser General Public
6 : : * License as published by the Free Software Foundation; either
7 : : * version 2.1 of the License, or (at your option) any later version.
8 : : *
9 : : * libplacebo is distributed in the hope that it will be useful,
10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : * GNU Lesser General Public License for more details.
13 : : *
14 : : * You should have received a copy of the GNU Lesser General Public
15 : : * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #include <math.h>
19 : :
20 : : #include "common.h"
21 : :
22 : 43921 : void pl_str_append_asprintf_c(void *alloc, pl_str *str, const char *fmt, ...)
23 : : {
24 : : va_list ap;
25 : 43921 : va_start(ap, fmt);
26 : 43921 : pl_str_append_vasprintf_c(alloc, str, fmt, ap);
27 : 43921 : va_end(ap);
28 : 43921 : }
29 : :
30 : 43921 : void pl_str_append_vasprintf_c(void *alloc, pl_str *str, const char *fmt,
31 : : va_list ap)
32 : : {
33 [ + + ]: 134544 : for (const char *c; (c = strchr(fmt, '%')) != NULL; fmt = c + 1) {
34 : : // Append the preceding string literal
35 : 90623 : pl_str_append_raw(alloc, str, fmt, c - fmt);
36 : 90623 : c++; // skip '%'
37 : :
38 : : char buf[32];
39 : : int len;
40 : :
41 : : // The format character follows the % sign
42 [ + + + - : 90623 : switch (c[0]) {
+ + + + +
+ - ]
43 : 74 : case '%':
44 : 74 : pl_str_append_raw(alloc, str, c, 1);
45 : 421 : continue;
46 : 544 : case 's': {
47 : 272 : const char *arg = va_arg(ap, const char *);
48 : 272 : pl_str_append_raw(alloc, str, arg, strlen(arg));
49 : 272 : continue;
50 : : }
51 : 1 : case '.': { // only used for %.*s
52 [ - + ]: 1 : assert(c[1] == '*');
53 [ - + ]: 1 : assert(c[2] == 's');
54 : 1 : len = va_arg(ap, int);
55 : 1 : pl_str_append_raw(alloc, str, va_arg(ap, char *), len);
56 : 1 : c += 2; // skip '*s'
57 : 1 : continue;
58 : : }
59 : 0 : case 'c':
60 : 0 : buf[0] = (char) va_arg(ap, int);
61 : : len = 1;
62 : 0 : break;
63 : 63058 : case 'd':
64 : 63058 : len = pl_str_print_int(buf, sizeof(buf), va_arg(ap, int));
65 : 63058 : break;
66 : 26660 : case 'h': ; // only used for %hx
67 [ - + ]: 26660 : assert(c[1] == 'x');
68 : 26660 : len = pl_str_print_hex(buf, sizeof(buf), (unsigned short) va_arg(ap, unsigned int));
69 : 26660 : c++;
70 : 26660 : break;
71 : 80 : case 'u':
72 : 80 : len = pl_str_print_uint(buf, sizeof(buf), va_arg(ap, unsigned int));
73 : 80 : break;
74 : 1 : case 'l':
75 [ - + ]: 1 : assert(c[1] == 'l');
76 [ - + - ]: 1 : switch (c[2]) {
77 : 0 : case 'u':
78 : 0 : len = pl_str_print_uint64(buf, sizeof(buf), va_arg(ap, unsigned long long));
79 : 0 : break;
80 : 1 : case 'd':
81 : 1 : len = pl_str_print_int64(buf, sizeof(buf), va_arg(ap, long long));
82 : 1 : break;
83 : 0 : default: pl_unreachable();
84 : : }
85 : 1 : c += 2;
86 : 1 : break;
87 : 1 : case 'z':
88 [ - + ]: 1 : assert(c[1] == 'u');
89 : 1 : len = pl_str_print_uint64(buf, sizeof(buf), va_arg(ap, size_t));
90 : 1 : c++;
91 : 1 : break;
92 : 476 : case 'f':
93 : 476 : len = pl_str_print_double(buf, sizeof(buf), va_arg(ap, double));
94 : 476 : break;
95 : 0 : default:
96 : 0 : fprintf(stderr, "Invalid conversion character: '%c'!\n", c[0]);
97 : 0 : abort();
98 : : }
99 : :
100 : 90276 : pl_str_append_raw(alloc, str, buf, len);
101 : : }
102 : :
103 : : // Append the remaining string literal
104 : 43921 : pl_str_append(alloc, str, pl_str0(fmt));
105 : 43921 : }
106 : :
107 : 25977 : size_t pl_str_append_memprintf_c(void *alloc, pl_str *str, const char *fmt,
108 : : const void *args)
109 : : {
110 : : const uint8_t *ptr = args;
111 : :
112 [ + + ]: 93039 : for (const char *c; (c = strchr(fmt, '%')) != NULL; fmt = c + 1) {
113 : 67062 : pl_str_append_raw(alloc, str, fmt, c - fmt);
114 : 67062 : c++;
115 : :
116 : : char buf[32];
117 : : int len;
118 : :
119 : : #define LOAD(var) \
120 : : do { \
121 : : memcpy(&(var), ptr, sizeof(var)); \
122 : : ptr += sizeof(var); \
123 : : } while (0)
124 : :
125 [ + + + + : 67062 : switch (c[0]) {
+ + + + +
+ - ]
126 : 189 : case '%':
127 : 189 : pl_str_append_raw(alloc, str, c, 1);
128 : 189 : continue;
129 : 11878 : case 's': {
130 : 11878 : len = strlen((const char *) ptr);
131 : 11878 : pl_str_append_raw(alloc, str, ptr, len);
132 : 11878 : ptr += len + 1; // also skip \0
133 : 11878 : continue;
134 : : }
135 : 237 : case '.': {
136 [ - + ]: 237 : assert(c[1] == '*');
137 [ - + ]: 237 : assert(c[2] == 's');
138 : 237 : LOAD(len);
139 : 237 : pl_str_append_raw(alloc, str, ptr, len);
140 : 237 : ptr += len; // no trailing \0
141 : 237 : c += 2;
142 : 237 : continue;
143 : : }
144 : : case 'c':
145 : 6323 : LOAD(buf[0]);
146 : 6323 : len = 1;
147 : 6323 : break;
148 : : case 'd': ;
149 : : int d;
150 : 14834 : LOAD(d);
151 : 14834 : len = pl_str_print_int(buf, sizeof(buf), d);
152 : 14834 : break;
153 : 27457 : case 'h': ;
154 [ - + ]: 27457 : assert(c[1] == 'x');
155 : : unsigned short hx;
156 : 27457 : LOAD(hx);
157 : 27457 : len = pl_str_print_hex(buf, sizeof(buf), hx);
158 : 27457 : c++;
159 : 27457 : break;
160 : : case 'u': ;
161 : : unsigned u;
162 : 1847 : LOAD(u);
163 : 1847 : len = pl_str_print_uint(buf, sizeof(buf), u);
164 : 1847 : break;
165 : 67 : case 'l':
166 [ - + ]: 67 : assert(c[1] == 'l');
167 [ + + - ]: 67 : switch (c[2]) {
168 : : case 'u': ;
169 : : long long unsigned llu;
170 : 66 : LOAD(llu);
171 : 66 : len = pl_str_print_uint64(buf, sizeof(buf), llu);
172 : 66 : break;
173 : : case 'd': ;
174 : : long long int lld;
175 : 1 : LOAD(lld);
176 : 1 : len = pl_str_print_int64(buf, sizeof(buf), lld);
177 : 1 : break;
178 : 0 : default: pl_unreachable();
179 : : }
180 : 67 : c += 2;
181 : 67 : break;
182 : 1224 : case 'z': ;
183 [ - + ]: 1224 : assert(c[1] == 'u');
184 : : size_t zu;
185 : 1224 : LOAD(zu);
186 : 1224 : len = pl_str_print_uint64(buf, sizeof(buf), zu);
187 : 1224 : c++;
188 : 1224 : break;
189 : : case 'f': ;
190 : : double f;
191 : 3006 : LOAD(f);
192 : 3006 : len = pl_str_print_double(buf, sizeof(buf), f);
193 : 3006 : break;
194 : 0 : default:
195 : 0 : fprintf(stderr, "Invalid conversion character: '%c'!\n", c[0]);
196 : 0 : abort();
197 : : }
198 : :
199 : 54758 : pl_str_append_raw(alloc, str, buf, len);
200 : : }
201 : : #undef LOAD
202 : :
203 : 25977 : pl_str_append(alloc, str, pl_str0(fmt));
204 : 25977 : return (uintptr_t) ptr - (uintptr_t) args;
205 : : }
|