#ifndef _LIBCPP_PRINT
#define _LIBCPP_PRINT
#include <__assert>
#include <__concepts/same_as.h>
#include <__config>
#include <__system_error/system_error.h>
#include <__utility/forward.h>
#include <cerrno>
#include <cstdio>
#include <format>
#include <string>
#include <string_view>
#include <version>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#ifdef _LIBCPP_WIN32API
_LIBCPP_EXPORTED_FROM_ABI bool __is_windows_terminal(FILE* __stream);
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
_LIBCPP_EXPORTED_FROM_ABI void __write_to_windows_console(FILE* __stream, wstring_view __view);
# endif
#elif __has_include(<unistd.h>)
_LIBCPP_EXPORTED_FROM_ABI bool __is_posix_terminal(FILE* __stream);
#endif
#if _LIBCPP_STD_VER >= 23
# ifndef _LIBCPP_HAS_NO_UNICODE
namespace __unicode {
# ifdef _LIBCPP_SHORT_WCHAR
template <class _Tp>
concept __utf16_code_unit =
same_as<_Tp, char16_t>
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|| same_as<_Tp, wchar_t>
# endif
;
template <class _Tp>
concept __utf32_code_unit = same_as<_Tp, char32_t>;
# else
template <class _Tp>
concept __utf16_code_unit = same_as<_Tp, char16_t>;
template <class _Tp>
concept __utf32_code_unit =
same_as<_Tp, char32_t>
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|| same_as<_Tp, wchar_t>
# endif
;
# endif
template <class _OutIt>
_LIBCPP_HIDE_FROM_ABI constexpr void __encode(_OutIt&, char32_t) = delete;
template <class _OutIt>
requires __utf16_code_unit<iter_value_t<_OutIt>>
_LIBCPP_HIDE_FROM_ABI constexpr void __encode(_OutIt& __out_it, char32_t __value) {
_LIBCPP_ASSERT_UNCATEGORIZED(__is_scalar_value(__value), "an invalid unicode scalar value results in invalid UTF-16");
if (__value < 0x10000) {
*__out_it++ = __value;
return;
}
__value -= 0x10000;
*__out_it++ = 0xd800 + (__value >> 10);
*__out_it++ = 0xdc00 + (__value & 0x3FF);
}
template <class _OutIt>
requires __utf32_code_unit<iter_value_t<_OutIt>>
_LIBCPP_HIDE_FROM_ABI constexpr void __encode(_OutIt& __out_it, char32_t __value) {
_LIBCPP_ASSERT_UNCATEGORIZED(__is_scalar_value(__value), "an invalid unicode scalar value results in invalid UTF-32");
*__out_it++ = __value;
}
template <class _OutIt, input_iterator _InIt>
requires output_iterator<_OutIt, const iter_value_t<_OutIt>&> && (!same_as<iter_value_t<_OutIt>, iter_value_t<_InIt>>)
_LIBCPP_HIDE_FROM_ABI constexpr _OutIt __transcode(_InIt __first, _InIt __last, _OutIt __out_it) {
basic_string_view<iter_value_t<_InIt>> __data{__first, __last};
__code_point_view<iter_value_t<_InIt>> __view{__data.begin(), __data.end()};
while (!__view.__at_end())
__unicode::__encode(__out_it, __view.__consume().__code_point);
return __out_it;
}
}
# endif
namespace __print {
# ifdef _LIBCPP_HAS_NO_UNICODE
inline constexpr bool __use_unicode_execution_charset = false;
# elif defined(_MSVC_EXECUTION_CHARACTER_SET)
inline constexpr bool __use_unicode_execution_charset = _MSVC_EXECUTION_CHARACTER_SET == 65001;
# else
inline constexpr bool __use_unicode_execution_charset = true;
# endif
_LIBCPP_HIDE_FROM_ABI inline bool __is_terminal([[maybe_unused]] FILE* __stream) {
# ifdef _LIBCPP_TESTING_PRINT_IS_TERMINAL
return _LIBCPP_TESTING_PRINT_IS_TERMINAL(__stream);
# elif _LIBCPP_AVAILABILITY_HAS_PRINT == 0 || defined(_LIBCPP_HAS_NO_TERMINAL)
return false;
# elif defined(_LIBCPP_WIN32API)
return std::__is_windows_terminal(__stream);
# elif __has_include(<unistd.h>)
return std::__is_posix_terminal(__stream);
# else
# error "Provide a way to determine whether a FILE* is a terminal"
# endif
}
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void
__vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl) {
_LIBCPP_ASSERT_NON_NULL(__stream, "__stream must be a valid pointer to an output C stream");
string __str = std::vformat(__fmt, __args);
if (__write_nl)
__str.push_back('\n');
size_t __size = fwrite(__str.data(), 1, __str.size(), __stream);
if (__size < __str.size()) {
if (std::feof(__stream))
std::__throw_system_error(EIO, "EOF while writing the formatted output");
std::__throw_system_error(std::ferror(__stream), "failed to write formatted output");
}
}
# ifndef _LIBCPP_HAS_NO_UNICODE
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void
__vprint_unicode_posix(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl, bool __is_terminal) {
if (__is_terminal)
std::fflush(__stream);
__print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl);
}
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void
__vprint_unicode_windows(FILE* __stream, string_view __fmt, format_args __args, bool __write_nl, bool __is_terminal) {
if (!__is_terminal)
return __print::__vprint_nonunicode(__stream, __fmt, __args, __write_nl);
std::fflush(__stream);
string __str = std::vformat(__fmt, __args);
__format::__retarget_buffer<wchar_t> __buffer{__str.size()};
__unicode::__transcode(__str.begin(), __str.end(), __buffer.__make_output_iterator());
if (__write_nl)
__buffer.push_back(L'\n');
[[maybe_unused]] wstring_view __view = __buffer.__view();
# ifdef _LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION
_LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION(__stream, __view);
# elif defined(_LIBCPP_WIN32API)
std::__write_to_windows_console(__stream, __view);
# else
std::__throw_runtime_error("No defintion of _LIBCPP_TESTING_PRINT_WRITE_TO_WINDOWS_CONSOLE_FUNCTION and "
"__write_to_windows_console is not available.");
# endif
}
# endif
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void
__vprint_unicode([[maybe_unused]] FILE* __stream,
[[maybe_unused]] string_view __fmt,
[[maybe_unused]] format_args __args,
[[maybe_unused]] bool __write_nl) {
_LIBCPP_ASSERT_NON_NULL(__stream, "__stream must be a valid pointer to an output C stream");
# ifndef _LIBCPP_WIN32API
__print::__vprint_unicode_posix(__stream, __fmt, __args, __write_nl, __print::__is_terminal(__stream));
# elif !defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS)
__print::__vprint_unicode_windows(__stream, __fmt, __args, __write_nl, __print::__is_terminal(__stream));
# else
# error "Windows builds with wchar_t disabled are not supported."
# endif
}
# endif
}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI void print(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) {
# ifndef _LIBCPP_HAS_NO_UNICODE
if constexpr (__print::__use_unicode_execution_charset)
__print::__vprint_unicode(__stream, __fmt.get(), std::make_format_args(__args...), false);
else
__print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), false);
# else
__print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), false);
# endif
}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI void print(format_string<_Args...> __fmt, _Args&&... __args) {
std::print(stdout, __fmt, std::forward<_Args>(__args)...);
}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI void println(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args) {
# ifndef _LIBCPP_HAS_NO_UNICODE
if constexpr (__print::__use_unicode_execution_charset)
__print::__vprint_unicode(__stream, __fmt.get(), std::make_format_args(__args...), true);
else
__print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), true);
# else
__print::__vprint_nonunicode(__stream, __fmt.get(), std::make_format_args(__args...), true);
# endif
}
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void println(FILE* __stream) {
std::print(__stream, "\n");
}
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void println() {
println(stdout);
}
template <class... _Args>
_LIBCPP_HIDE_FROM_ABI void println(format_string<_Args...> __fmt, _Args&&... __args) {
std::println(stdout, __fmt, std::forward<_Args>(__args)...);
}
# ifndef _LIBCPP_HAS_NO_UNICODE
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(FILE* __stream, string_view __fmt, format_args __args) {
__print::__vprint_unicode(__stream, __fmt, __args, false);
}
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void vprint_unicode(string_view __fmt, format_args __args) {
std::vprint_unicode(stdout, __fmt, __args);
}
# endif
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args) {
__print::__vprint_nonunicode(__stream, __fmt, __args, false);
}
template <class = void>
_LIBCPP_HIDE_FROM_ABI inline void vprint_nonunicode(string_view __fmt, format_args __args) {
std::vprint_nonunicode(stdout, __fmt, __args);
}
#endif
_LIBCPP_END_NAMESPACE_STD
#endif