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