From ff6e3c025658a5fa1affd094f220b623e7e1b24b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 22:38:23 +0200 Subject: Adding upstream version 6.338.2. Signed-off-by: Daniel Baumann --- src/format.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/format.c (limited to 'src/format.c') diff --git a/src/format.c b/src/format.c new file mode 100644 index 0000000..458d493 --- /dev/null +++ b/src/format.c @@ -0,0 +1,205 @@ +/* + * This file is part of libplacebo. + * + * libplacebo is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * libplacebo is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with libplacebo. If not, see . + */ + +#include + +#include "common.h" + +void pl_str_append_asprintf_c(void *alloc, pl_str *str, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + pl_str_append_vasprintf_c(alloc, str, fmt, ap); + va_end(ap); +} + +void pl_str_append_vasprintf_c(void *alloc, pl_str *str, const char *fmt, + va_list ap) +{ + for (const char *c; (c = strchr(fmt, '%')) != NULL; fmt = c + 1) { + // Append the preceding string literal + pl_str_append_raw(alloc, str, fmt, c - fmt); + c++; // skip '%' + + char buf[32]; + int len; + + // The format character follows the % sign + switch (c[0]) { + case '%': + pl_str_append_raw(alloc, str, c, 1); + continue; + case 's': { + const char *arg = va_arg(ap, const char *); + pl_str_append_raw(alloc, str, arg, strlen(arg)); + continue; + } + case '.': { // only used for %.*s + assert(c[1] == '*'); + assert(c[2] == 's'); + len = va_arg(ap, int); + pl_str_append_raw(alloc, str, va_arg(ap, char *), len); + c += 2; // skip '*s' + continue; + } + case 'c': + buf[0] = (char) va_arg(ap, int); + len = 1; + break; + case 'd': + len = pl_str_print_int(buf, sizeof(buf), va_arg(ap, int)); + break; + case 'h': ; // only used for %hx + assert(c[1] == 'x'); + len = pl_str_print_hex(buf, sizeof(buf), (unsigned short) va_arg(ap, unsigned int)); + c++; + break; + case 'u': + len = pl_str_print_uint(buf, sizeof(buf), va_arg(ap, unsigned int)); + break; + case 'l': + assert(c[1] == 'l'); + switch (c[2]) { + case 'u': + len = pl_str_print_uint64(buf, sizeof(buf), va_arg(ap, unsigned long long)); + break; + case 'd': + len = pl_str_print_int64(buf, sizeof(buf), va_arg(ap, long long)); + break; + default: pl_unreachable(); + } + c += 2; + break; + case 'z': + assert(c[1] == 'u'); + len = pl_str_print_uint64(buf, sizeof(buf), va_arg(ap, size_t)); + c++; + break; + case 'f': + len = pl_str_print_double(buf, sizeof(buf), va_arg(ap, double)); + break; + default: + fprintf(stderr, "Invalid conversion character: '%c'!\n", c[0]); + abort(); + } + + pl_str_append_raw(alloc, str, buf, len); + } + + // Append the remaining string literal + pl_str_append(alloc, str, pl_str0(fmt)); +} + +size_t pl_str_append_memprintf_c(void *alloc, pl_str *str, const char *fmt, + const void *args) +{ + const uint8_t *ptr = args; + + for (const char *c; (c = strchr(fmt, '%')) != NULL; fmt = c + 1) { + pl_str_append_raw(alloc, str, fmt, c - fmt); + c++; + + char buf[32]; + int len; + +#define LOAD(var) \ + do { \ + memcpy(&(var), ptr, sizeof(var)); \ + ptr += sizeof(var); \ + } while (0) + + switch (c[0]) { + case '%': + pl_str_append_raw(alloc, str, c, 1); + continue; + case 's': { + len = strlen((const char *) ptr); + pl_str_append_raw(alloc, str, ptr, len); + ptr += len + 1; // also skip \0 + continue; + } + case '.': { + assert(c[1] == '*'); + assert(c[2] == 's'); + LOAD(len); + pl_str_append_raw(alloc, str, ptr, len); + ptr += len; // no trailing \0 + c += 2; + continue; + } + case 'c': + LOAD(buf[0]); + len = 1; + break; + case 'd': ; + int d; + LOAD(d); + len = pl_str_print_int(buf, sizeof(buf), d); + break; + case 'h': ; + assert(c[1] == 'x'); + unsigned short hx; + LOAD(hx); + len = pl_str_print_hex(buf, sizeof(buf), hx); + c++; + break; + case 'u': ; + unsigned u; + LOAD(u); + len = pl_str_print_uint(buf, sizeof(buf), u); + break; + case 'l': + assert(c[1] == 'l'); + switch (c[2]) { + case 'u': ; + long long unsigned llu; + LOAD(llu); + len = pl_str_print_uint64(buf, sizeof(buf), llu); + break; + case 'd': ; + long long int lld; + LOAD(lld); + len = pl_str_print_int64(buf, sizeof(buf), lld); + break; + default: pl_unreachable(); + } + c += 2; + break; + case 'z': ; + assert(c[1] == 'u'); + size_t zu; + LOAD(zu); + len = pl_str_print_uint64(buf, sizeof(buf), zu); + c++; + break; + case 'f': ; + double f; + LOAD(f); + len = pl_str_print_double(buf, sizeof(buf), f); + break; + default: + fprintf(stderr, "Invalid conversion character: '%c'!\n", c[0]); + abort(); + } + + pl_str_append_raw(alloc, str, buf, len); + } +#undef LOAD + + pl_str_append(alloc, str, pl_str0(fmt)); + return (uintptr_t) ptr - (uintptr_t) args; +} -- cgit v1.2.3