1b3127a2dSJohn Baldwin /*-
2b3127a2dSJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause
3b3127a2dSJohn Baldwin *
4b3127a2dSJohn Baldwin * Copyright (c) 2025 Chelsio Communications, Inc.
5b3127a2dSJohn Baldwin * Written by: John Baldwin <jhb@FreeBSD.org>
6b3127a2dSJohn Baldwin */
7b3127a2dSJohn Baldwin
8b3127a2dSJohn Baldwin #include <cstdarg>
9b3127a2dSJohn Baldwin #include <cstdio>
10b3127a2dSJohn Baldwin #include <string>
11b3127a2dSJohn Baldwin
12b3127a2dSJohn Baldwin #include "libutil++.hh"
13b3127a2dSJohn Baldwin
14b3127a2dSJohn Baldwin static int
stringf_write(void * cookie,const char * buf,int len)15b3127a2dSJohn Baldwin stringf_write(void *cookie, const char *buf, int len)
16b3127a2dSJohn Baldwin {
17b3127a2dSJohn Baldwin std::string *str = reinterpret_cast<std::string *>(cookie);
18b3127a2dSJohn Baldwin try {
19b3127a2dSJohn Baldwin str->append(buf, len);
20b3127a2dSJohn Baldwin } catch (std::bad_alloc) {
21b3127a2dSJohn Baldwin errno = ENOMEM;
22b3127a2dSJohn Baldwin return (-1);
23b3127a2dSJohn Baldwin } catch (std::length_error) {
24b3127a2dSJohn Baldwin errno = EFBIG;
25b3127a2dSJohn Baldwin return (-1);
26b3127a2dSJohn Baldwin }
27b3127a2dSJohn Baldwin return (len);
28b3127a2dSJohn Baldwin }
29b3127a2dSJohn Baldwin
30b3127a2dSJohn Baldwin std::string
stringf(const char * fmt,va_list ap)31b3127a2dSJohn Baldwin freebsd::stringf(const char *fmt, va_list ap)
32b3127a2dSJohn Baldwin {
33b3127a2dSJohn Baldwin std::string str;
34b3127a2dSJohn Baldwin freebsd::FILE_up fp(fwopen(reinterpret_cast<void *>(&str),
35b3127a2dSJohn Baldwin stringf_write));
36b3127a2dSJohn Baldwin
37b3127a2dSJohn Baldwin vfprintf(fp.get(), fmt, ap);
38b3127a2dSJohn Baldwin
39b3127a2dSJohn Baldwin if (ferror(fp.get()))
40b3127a2dSJohn Baldwin throw std::bad_alloc();
41b3127a2dSJohn Baldwin fp.reset(nullptr);
42b3127a2dSJohn Baldwin
43b3127a2dSJohn Baldwin return str;
44b3127a2dSJohn Baldwin }
45b3127a2dSJohn Baldwin
46b3127a2dSJohn Baldwin std::string
stringf(const char * fmt,...)47b3127a2dSJohn Baldwin freebsd::stringf(const char *fmt, ...)
48b3127a2dSJohn Baldwin {
49b3127a2dSJohn Baldwin std::va_list ap;
50b3127a2dSJohn Baldwin std::string str;
51b3127a2dSJohn Baldwin
52b3127a2dSJohn Baldwin va_start(ap, fmt);
53b3127a2dSJohn Baldwin str = freebsd::stringf(fmt, ap);
54b3127a2dSJohn Baldwin va_end(ap);
55b3127a2dSJohn Baldwin
56b3127a2dSJohn Baldwin return str;
57b3127a2dSJohn Baldwin }
58