1//===----------------------------------------------------------------------===////
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===////
8
9#ifndef FILESYSTEM_FORMAT_STRING_H
10#define FILESYSTEM_FORMAT_STRING_H
11
12#include <__assert>
13#include <__config>
14#include <__utility/scope_guard.h>
15#include <array>
16#include <cstdarg>
17#include <cstddef>
18#include <cstdio>
19#include <string>
20
21#if defined(_LIBCPP_WIN32API)
22# define PATHSTR(x) (L##x)
23# define PATH_CSTR_FMT "\"%ls\""
24#else
25# define PATHSTR(x) (x)
26# define PATH_CSTR_FMT "\"%s\""
27#endif
28
29_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
30
31namespace detail {
32
33inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 0) string vformat_string(const char* msg, va_list ap) {
34 array<char, 256> buf;
35
36 va_list apcopy;
37 va_copy(apcopy, ap);
38 int size = ::vsnprintf(s: buf.data(), maxlen: buf.size(), format: msg, arg: apcopy);
39 va_end(apcopy);
40
41 string result;
42 if (static_cast<size_t>(size) < buf.size()) {
43 result.assign(s: buf.data(), n: static_cast<size_t>(size));
44 } else {
45 // we did not provide a long enough buffer on our first attempt. The
46 // return value is the number of bytes (excluding the null byte) that are
47 // needed for formatting.
48 result.resize_and_overwrite(n: size, op: [&](char* res, size_t n) { return ::vsnprintf(s: res, maxlen: n, format: msg, arg: ap); });
49 _LIBCPP_ASSERT_INTERNAL(static_cast<size_t>(size) == result.size(),
50 "vsnprintf did not result in the same number of characters as the first attempt?");
51 }
52 return result;
53}
54
55inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) string format_string(const char* msg, ...) {
56 string ret;
57 va_list ap;
58 va_start(ap, msg);
59 __scope_guard guard([&] { va_end(ap); });
60 ret = detail::vformat_string(msg, ap);
61 return ret;
62}
63
64} // namespace detail
65
66_LIBCPP_END_NAMESPACE_FILESYSTEM
67
68#endif // FILESYSTEM_FORMAT_STRING_H
69