1c7d3c844SLouis Dionne //===----------------------------------------------------------------------===//// 2c7d3c844SLouis Dionne // 3c7d3c844SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c7d3c844SLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 5c7d3c844SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c7d3c844SLouis Dionne // 7c7d3c844SLouis Dionne //===----------------------------------------------------------------------===//// 8c7d3c844SLouis Dionne 9c7d3c844SLouis Dionne #ifndef FILESYSTEM_FORMAT_STRING_H 10c7d3c844SLouis Dionne #define FILESYSTEM_FORMAT_STRING_H 11c7d3c844SLouis Dionne 12c7d3c844SLouis Dionne #include <__assert> 13c7d3c844SLouis Dionne #include <__config> 14c7d3c844SLouis Dionne #include <array> 15c7d3c844SLouis Dionne #include <cstdarg> 16c7d3c844SLouis Dionne #include <cstddef> 17c7d3c844SLouis Dionne #include <cstdio> 18c7d3c844SLouis Dionne #include <string> 19c7d3c844SLouis Dionne 20c7d3c844SLouis Dionne #if defined(_LIBCPP_WIN32API) 21c7d3c844SLouis Dionne # define PATHSTR(x) (L##x) 22c7d3c844SLouis Dionne # define PATH_CSTR_FMT "\"%ls\"" 23c7d3c844SLouis Dionne #else 24c7d3c844SLouis Dionne # define PATHSTR(x) (x) 25c7d3c844SLouis Dionne # define PATH_CSTR_FMT "\"%s\"" 26c7d3c844SLouis Dionne #endif 27c7d3c844SLouis Dionne 28c7d3c844SLouis Dionne _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM 29c7d3c844SLouis Dionne 30c7d3c844SLouis Dionne namespace detail { 31c7d3c844SLouis Dionne 3221853b96SLouis Dionne inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 0) string vformat_string(const char* msg, va_list ap) { 33c7d3c844SLouis Dionne array<char, 256> buf; 34c7d3c844SLouis Dionne 35c7d3c844SLouis Dionne va_list apcopy; 36c7d3c844SLouis Dionne va_copy(apcopy, ap); 37c7d3c844SLouis Dionne int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); 38c7d3c844SLouis Dionne va_end(apcopy); 39c7d3c844SLouis Dionne 40c7d3c844SLouis Dionne string result; 41c7d3c844SLouis Dionne if (static_cast<size_t>(ret) < buf.size()) { 42c7d3c844SLouis Dionne result.assign(buf.data(), static_cast<size_t>(ret)); 43c7d3c844SLouis Dionne } else { 44c7d3c844SLouis Dionne // we did not provide a long enough buffer on our first attempt. The 45c7d3c844SLouis Dionne // return value is the number of bytes (excluding the null byte) that are 46c7d3c844SLouis Dionne // needed for formatting. 47c7d3c844SLouis Dionne size_t size_with_null = static_cast<size_t>(ret) + 1; 48c7d3c844SLouis Dionne result.__resize_default_init(size_with_null - 1); 49c7d3c844SLouis Dionne ret = ::vsnprintf(&result[0], size_with_null, msg, ap); 504f215fddSKonstantin Varlamov _LIBCPP_ASSERT_INTERNAL(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); 51c7d3c844SLouis Dionne } 52c7d3c844SLouis Dionne return result; 53c7d3c844SLouis Dionne } 54c7d3c844SLouis Dionne 5521853b96SLouis Dionne inline _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 1, 2) string format_string(const char* msg, ...) { 56c7d3c844SLouis Dionne string ret; 57c7d3c844SLouis Dionne va_list ap; 58c7d3c844SLouis Dionne va_start(ap, msg); 59*ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 60c7d3c844SLouis Dionne try { 61*ba87515fSNikolas Klauser #endif // _LIBCPP_HAS_EXCEPTIONS 62c7d3c844SLouis Dionne ret = detail::vformat_string(msg, ap); 63*ba87515fSNikolas Klauser #if _LIBCPP_HAS_EXCEPTIONS 64c7d3c844SLouis Dionne } catch (...) { 65c7d3c844SLouis Dionne va_end(ap); 66c7d3c844SLouis Dionne throw; 67c7d3c844SLouis Dionne } 68*ba87515fSNikolas Klauser #endif // _LIBCPP_HAS_EXCEPTIONS 69c7d3c844SLouis Dionne va_end(ap); 70c7d3c844SLouis Dionne return ret; 71c7d3c844SLouis Dionne } 72c7d3c844SLouis Dionne 73953af0e7SLouis Dionne } // namespace detail 74c7d3c844SLouis Dionne 75c7d3c844SLouis Dionne _LIBCPP_END_NAMESPACE_FILESYSTEM 76c7d3c844SLouis Dionne 77c7d3c844SLouis Dionne #endif // FILESYSTEM_FORMAT_STRING_H 78