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