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 <array> |
15 | #include <cstdarg> |
16 | #include <cstddef> |
17 | #include <cstdio> |
18 | #include <string> |
19 | |
20 | #if defined(_LIBCPP_WIN32API) |
21 | # define PATHSTR(x) (L##x) |
22 | # define PATH_CSTR_FMT "\"%ls\"" |
23 | #else |
24 | # define PATHSTR(x) (x) |
25 | # define PATH_CSTR_FMT "\"%s\"" |
26 | #endif |
27 | |
28 | _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM |
29 | |
30 | namespace detail { |
31 | |
32 | inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 0) string vformat_string(const char* msg, va_list ap) { |
33 | array<char, 256> buf; |
34 | |
35 | va_list apcopy; |
36 | va_copy(apcopy, ap); |
37 | int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); |
38 | va_end(apcopy); |
39 | |
40 | string result; |
41 | if (static_cast<size_t>(ret) < buf.size()) { |
42 | result.assign(buf.data(), static_cast<size_t>(ret)); |
43 | } else { |
44 | // we did not provide a long enough buffer on our first attempt. The |
45 | // return value is the number of bytes (excluding the null byte) that are |
46 | // needed for formatting. |
47 | size_t size_with_null = static_cast<size_t>(ret) + 1; |
48 | result.__resize_default_init(size_with_null - 1); |
49 | ret = ::vsnprintf(&result[0], size_with_null, msg, ap); |
50 | _LIBCPP_ASSERT_INTERNAL(static_cast<size_t>(ret) == (size_with_null - 1), "TODO" ); |
51 | } |
52 | return result; |
53 | } |
54 | |
55 | inline _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 | #ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
60 | try { |
61 | #endif // _LIBCPP_HAS_NO_EXCEPTIONS |
62 | ret = detail::vformat_string(msg, ap); |
63 | #ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
64 | } catch (...) { |
65 | va_end(ap); |
66 | throw; |
67 | } |
68 | #endif // _LIBCPP_HAS_NO_EXCEPTIONS |
69 | va_end(ap); |
70 | return ret; |
71 | } |
72 | |
73 | } // end namespace detail |
74 | |
75 | _LIBCPP_END_NAMESPACE_FILESYSTEM |
76 | |
77 | #endif // FILESYSTEM_FORMAT_STRING_H |
78 | |