aboutsummaryrefslogtreecommitdiff
path: root/lib/libutil++/stringf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutil++/stringf.cc')
-rw-r--r--lib/libutil++/stringf.cc57
1 files changed, 57 insertions, 0 deletions
diff --git a/lib/libutil++/stringf.cc b/lib/libutil++/stringf.cc
new file mode 100644
index 000000000000..8c24167d70ac
--- /dev/null
+++ b/lib/libutil++/stringf.cc
@@ -0,0 +1,57 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <cstdarg>
+#include <cstdio>
+#include <string>
+
+#include "libutil++.hh"
+
+static int
+stringf_write(void *cookie, const char *buf, int len)
+{
+ std::string *str = reinterpret_cast<std::string *>(cookie);
+ try {
+ str->append(buf, len);
+ } catch (std::bad_alloc) {
+ errno = ENOMEM;
+ return (-1);
+ } catch (std::length_error) {
+ errno = EFBIG;
+ return (-1);
+ }
+ return (len);
+}
+
+std::string
+freebsd::stringf(const char *fmt, va_list ap)
+{
+ std::string str;
+ freebsd::FILE_up fp(fwopen(reinterpret_cast<void *>(&str),
+ stringf_write));
+
+ vfprintf(fp.get(), fmt, ap);
+
+ if (ferror(fp.get()))
+ throw std::bad_alloc();
+ fp.reset(nullptr);
+
+ return str;
+}
+
+std::string
+freebsd::stringf(const char *fmt, ...)
+{
+ std::va_list ap;
+ std::string str;
+
+ va_start(ap, fmt);
+ str = freebsd::stringf(fmt, ap);
+ va_end(ap);
+
+ return str;
+}