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 : : #pragma once
19 : :
20 : : #include "common.h"
21 : :
22 : : PL_API_BEGIN
23 : :
24 : : typedef struct pl_str {
25 : : uint8_t *buf;
26 : : size_t len;
27 : : } pl_str;
28 : :
29 : : // For formatting with "%.*s"
30 : : #define PL_STR_FMT(str) (int)((str).len), ((str).buf ? (char *)((str).buf) : "")
31 : :
32 : : static inline pl_str pl_str0(const char *str)
33 : : {
34 : 14 : return (pl_str) {
35 : : .buf = (uint8_t *) str,
36 [ + - + - : 121567 : .len = str ? strlen(str) : 0,
+ - + - +
- ]
37 : : };
38 : : }
39 : :
40 : : // Macro version of pl_str0, for constants
41 : : #define PL_STR0(str) ((pl_str) { (uint8_t *) (str), (str) ? strlen(str) : 0 })
42 : :
43 : : static inline pl_str pl_strdup(void *alloc, pl_str str)
44 : : {
45 : : return (pl_str) {
46 [ + - ]: 10 : .buf = (uint8_t *) (str.len ? pl_memdup(alloc, str.buf, str.len) : NULL),
47 : : .len = str.len,
48 : : };
49 : : }
50 : :
51 : : // Always returns a valid string
52 : : static inline char *pl_strdup0(void *alloc, pl_str str)
53 : : {
54 [ + - + - : 101 : return pl_strndup0(alloc, str.len ? (char *) str.buf : "", str.len);
+ - + - +
- ]
55 : : }
56 : :
57 : : // Adds a trailing \0 for convenience, even if `append` is an empty string
58 : : void pl_str_append(void *alloc, pl_str *str, pl_str append);
59 : :
60 : : // Like `pl_str_append` but for raw memory, omits trailing \0
61 : : void pl_str_append_raw(void *alloc, pl_str *str, const void *ptr, size_t size);
62 : :
63 : : // Locale-sensitive string functions
64 : : char *pl_asprintf(void *parent, const char *fmt, ...)
65 : : PL_PRINTF(2, 3);
66 : : char *pl_vasprintf(void *parent, const char *fmt, va_list ap)
67 : : PL_PRINTF(2, 0);
68 : : void pl_str_append_asprintf(void *alloc, pl_str *str, const char *fmt, ...)
69 : : PL_PRINTF(3, 4);
70 : : void pl_str_append_vasprintf(void *alloc, pl_str *str, const char *fmt, va_list va)
71 : : PL_PRINTF(3, 0);
72 : : int pl_str_sscanf(pl_str str, const char *fmt, ...);
73 : :
74 : : // Locale-invariant versions of append_(v)asprintf
75 : : //
76 : : // NOTE: These only support a small handful of modifiers. Check `format.c`
77 : : // for a list. Calling them on an invalid string will abort!
78 : : void pl_str_append_asprintf_c(void *alloc, pl_str *str, const char *fmt, ...)
79 : : PL_PRINTF(3, 4);
80 : : void pl_str_append_vasprintf_c(void *alloc, pl_str *str, const char *fmt, va_list va)
81 : : PL_PRINTF(3, 0);
82 : :
83 : : // Variant of the above which takes arguments directly from a pointer in memory,
84 : : // reading them incrementally (tightly packed). Returns the amount of bytes
85 : : // read from `args`, as determined by the following table:
86 : : //
87 : : // %c: sizeof(char)
88 : : // %d, %u: sizeof(int)
89 : : // %f: sizeof(double)
90 : : // %lld, %llu: sizeof(long long int)
91 : : // %zu: sizeof(size_t)
92 : : // %s: \0 terminated string
93 : : // %.*s: sizeof(int) + that many bytes (no \0 terminator)
94 : : size_t pl_str_append_memprintf_c(void *alloc, pl_str *str, const char *fmt,
95 : : const void *args)
96 : : PL_PRINTF(3, 0);
97 : :
98 : : // Locale-invariant number printing
99 : : int pl_str_print_hex(char *buf, size_t len, unsigned short n);
100 : : int pl_str_print_int(char *buf, size_t len, int n);
101 : : int pl_str_print_uint(char *buf, size_t len, unsigned int n);
102 : : int pl_str_print_int64(char *buf, size_t len, int64_t n);
103 : : int pl_str_print_uint64(char *buf, size_t len, uint64_t n);
104 : : int pl_str_print_float(char *buf, size_t len, float n);
105 : : int pl_str_print_double(char *buf, size_t len, double n);
106 : :
107 : : // Locale-invariant number parsing
108 : : bool pl_str_parse_hex(pl_str str, unsigned short *out);
109 : : bool pl_str_parse_int(pl_str str, int *out);
110 : : bool pl_str_parse_uint(pl_str str, unsigned int *out);
111 : : bool pl_str_parse_int64(pl_str str, int64_t *out);
112 : : bool pl_str_parse_uint64(pl_str str, uint64_t *out);
113 : : bool pl_str_parse_float(pl_str str, float *out);
114 : : bool pl_str_parse_double(pl_str str, double *out);
115 : :
116 : : // Variants of string.h functions
117 : : int pl_strchr(pl_str str, int c);
118 : : size_t pl_strspn(pl_str str, const char *accept);
119 : : size_t pl_strcspn(pl_str str, const char *reject);
120 : :
121 : : // Strip leading/trailing whitespace
122 : : pl_str pl_str_strip(pl_str str);
123 : :
124 : : // Generic functions for cutting up strings
125 : : static inline pl_str pl_str_take(pl_str str, size_t len)
126 : : {
127 : 592 : if (len < str.len)
128 : : str.len = len;
129 : : return str;
130 : : }
131 : :
132 : : static inline pl_str pl_str_drop(pl_str str, size_t len)
133 : : {
134 [ + + + + : 41973 : if (len >= str.len)
+ + + + ]
135 : : return (pl_str) { .buf = NULL, .len = 0 };
136 : :
137 : 41050 : str.buf += len;
138 : 41050 : str.len -= len;
139 : 41050 : return str;
140 : : }
141 : :
142 : : // Find a substring in another string, and return its index (or -1)
143 : : int pl_str_find(pl_str haystack, pl_str needle);
144 : :
145 : : // String splitting functions. These return the part of the string before
146 : : // the separator, and optionally the rest (in `out_rest`).
147 : : //
148 : : // Note that the separator is not included as part of either string.
149 : : pl_str pl_str_split_char(pl_str str, char sep, pl_str *out_rest);
150 : : pl_str pl_str_split_str(pl_str str, pl_str sep, pl_str *out_rest);
151 : :
152 : : // Like `pl_str_split_char`, but splits on any char in `seps`
153 : : pl_str pl_str_split_chars(pl_str str, const char *seps, pl_str *out_rest);
154 : :
155 : : static inline pl_str pl_str_getline(pl_str str, pl_str *out_rest)
156 : : {
157 : 263 : return pl_str_split_char(str, '\n', out_rest);
158 : : }
159 : :
160 : : // Decode a string containing hexadecimal data. All whitespace will be silently
161 : : // ignored. When successful, this allocates a new array to store the output.
162 : : bool pl_str_decode_hex(void *alloc, pl_str hex, pl_str *out);
163 : :
164 : 17315 : static inline bool pl_str_equals(pl_str str1, pl_str str2)
165 : : {
166 [ + + ]: 17315 : if (str1.len != str2.len)
167 : : return false;
168 [ + + + + ]: 758 : if (str1.buf == str2.buf || !str1.len)
169 : : return true;
170 : 679 : return memcmp(str1.buf, str2.buf, str1.len) == 0;
171 : : }
172 : :
173 : : static inline bool pl_str_startswith(pl_str str, pl_str prefix)
174 : : {
175 [ + - ]: 190 : if (!prefix.len)
176 : : return true;
177 [ + + + + ]: 1104 : if (str.len < prefix.len)
178 : : return false;
179 : 187 : return memcmp(str.buf, prefix.buf, prefix.len) == 0;
180 : : }
181 : :
182 : 266 : static inline bool pl_str_endswith(pl_str str, pl_str suffix)
183 : : {
184 [ + + ]: 266 : if (!suffix.len)
185 : : return true;
186 [ + + ]: 264 : if (str.len < suffix.len)
187 : : return false;
188 : 120 : return memcmp(str.buf + str.len - suffix.len, suffix.buf, suffix.len) == 0;
189 : : }
190 : :
191 [ + - ]: 968 : static inline bool pl_str_eatstart(pl_str *str, pl_str prefix)
192 : : {
193 [ + + ]: 927 : if (!pl_str_startswith(*str, prefix))
194 : : return false;
195 : :
196 : 409 : str->buf += prefix.len;
197 : 409 : str->len -= prefix.len;
198 : 409 : return true;
199 : : }
200 : :
201 : : static inline bool pl_str_eatend(pl_str *str, pl_str suffix)
202 : : {
203 [ + + ]: 263 : if (!pl_str_endswith(*str, suffix))
204 : : return false;
205 : :
206 : 31 : str->len -= suffix.len;
207 : 31 : return true;
208 : : }
209 : :
210 : : // Convenience wrappers for the above which save the use of a pl_str0
211 [ + - ]: 49 : static inline pl_str pl_str_split_str0(pl_str str, const char *sep, pl_str *out_rest)
212 : : {
213 : 49 : return pl_str_split_str(str, pl_str0(sep), out_rest);
214 : : }
215 : :
216 [ + - ]: 136 : static inline bool pl_str_startswith0(pl_str str, const char *prefix)
217 : : {
218 : 136 : return pl_str_startswith(str, pl_str0(prefix));
219 : : }
220 : :
221 : : static inline bool pl_str_endswith0(pl_str str, const char *suffix)
222 : : {
223 : : return pl_str_endswith(str, pl_str0(suffix));
224 : : }
225 : :
226 [ + - ]: 17249 : static inline bool pl_str_equals0(pl_str str1, const char *str2)
227 : : {
228 : 17249 : return pl_str_equals(str1, pl_str0(str2));
229 : : }
230 : :
231 [ + - ]: 968 : static inline bool pl_str_eatstart0(pl_str *str, const char *prefix)
232 : : {
233 : 968 : return pl_str_eatstart(str, pl_str0(prefix));
234 : : }
235 : :
236 [ + - ]: 263 : static inline bool pl_str_eatend0(pl_str *str, const char *prefix)
237 : : {
238 : 263 : return pl_str_eatend(str, pl_str0(prefix));
239 : : }
240 : :
241 : : // String building helpers, used to lazily construct a string by appending a
242 : : // series of string templates which can be executed on-demand into a final
243 : : // output buffer.
244 : : typedef struct pl_str_builder_t *pl_str_builder;
245 : :
246 : : // Returns the number of bytes consumed from `args`. Be warned that the pointer
247 : : // given will not necessarily be aligned to the type you need it as, so make
248 : : // sure to use `memcpy` or some other method of safely loading arbitrary data
249 : : // from memory.
250 : : typedef size_t (*pl_str_template)(void *alloc, pl_str *buf, const uint8_t *args);
251 : :
252 : : pl_str_builder pl_str_builder_alloc(void *alloc);
253 : : void pl_str_builder_free(pl_str_builder *builder);
254 : :
255 : : // Resets string builder without destroying buffer
256 : : void pl_str_builder_reset(pl_str_builder builder);
257 : :
258 : : // Returns a representative hash of the string builder's output, without
259 : : // actually executing it. Note that this is *not* the same as a pl_str_hash of
260 : : // the string builder's output.
261 : : //
262 : : // Note also that the output of this may not survive a process restart because
263 : : // of position-independent code and address randomization moving around the
264 : : // locatons of template functions, so special care must be taken not to
265 : : // compare such hashes across process invocations.
266 : : uint64_t pl_str_builder_hash(const pl_str_builder builder);
267 : :
268 : : // Executes a string builder, dispatching all templates. The resulting string
269 : : // is guaranteed to be \0-terminated, as a minor convenience.
270 : : //
271 : : // Calling any other `pl_str_builder_*` function on this builder causes the
272 : : // contents of the returned string to become undefined.
273 : : pl_str pl_str_builder_exec(pl_str_builder builder);
274 : :
275 : : // Append a template and its arguments to a string builder
276 : : void pl_str_builder_append(pl_str_builder builder, pl_str_template tmpl,
277 : : const void *args, size_t args_size);
278 : :
279 : : // Append an entire other `pl_str_builder` onto `builder`
280 : : void pl_str_builder_concat(pl_str_builder builder, const pl_str_builder append);
281 : :
282 : : // Append a constant string. This will only record &str into the buffer, which
283 : : // may have a number of unwanted consequences if the memory pointed at by
284 : : // `str` mutates at any point in time in the future, or if `str` is not
285 : : // at a stable location in memory.
286 : : //
287 : : // This is intended for strings which are compile-time constants.
288 : : void pl_str_builder_const_str(pl_str_builder builder, const char *str);
289 : :
290 : : // Append a string. This will make a full copy of `str`
291 : : void pl_str_builder_str(pl_str_builder builder, const pl_str str);
292 : : #define pl_str_builder_str0(b, str) pl_str_builder_str(b, pl_str0(str))
293 : :
294 : : // Append a string printf-style. This will preprocess `fmt` to determine the
295 : : // number and type of arguments. Supports the same format conversion characters
296 : : // as `pl_str_append_asprintf_c`.
297 : : void pl_str_builder_printf_c(pl_str_builder builder, const char *fmt, ...)
298 : : PL_PRINTF(2, 3);
299 : :
300 : : void pl_str_builder_vprintf_c(pl_str_builder builder, const char *fmt, va_list ap)
301 : : PL_PRINTF(2, 0);
302 : :
303 : : // Helper macro to specialize `pl_str_builder_printf_c` to
304 : : // `pl_str_builder_const_str` if it contains no format characters.
305 : : #define pl_str_builder_addf(builder, ...) do \
306 : : { \
307 : : if (_contains_fmt_chars(__VA_ARGS__)) { \
308 : : pl_str_builder_printf_c(builder, __VA_ARGS__); \
309 : : } else { \
310 : : pl_str_builder_const_str(builder, _get_fmt(__VA_ARGS__)); \
311 : : } \
312 : : } while (0)
313 : :
314 : : // Helper macros to deal with the non-portability of __VA_OPT__(,)
315 : : #define _contains_fmt_chars(fmt, ...) (strchr(fmt, '%'))
316 : : #define _get_fmt(fmt, ...) fmt
317 : :
318 : : PL_API_END
|