diff --git a/src/3rdparty/fmt/ostream.h b/src/3rdparty/fmt/ostream.h --- a/src/3rdparty/fmt/ostream.h +++ b/src/3rdparty/fmt/ostream.h @@ -10,18 +10,49 @@ #include // std::filebuf -#if defined(_WIN32) && defined(__GLIBCXX__) -# include -# include -#elif defined(_WIN32) && defined(_LIBCPP_VERSION) -# include <__std_stream> +#ifdef _WIN32 +# ifdef __GLIBCXX__ +# include +# include +# endif +# include #endif #include "format.h" FMT_BEGIN_NAMESPACE +namespace detail { -namespace detail { +template class formatbuf : public Streambuf { + private: + using char_type = typename Streambuf::char_type; + using streamsize = decltype(std::declval().sputn(nullptr, 0)); + using int_type = typename Streambuf::int_type; + using traits_type = typename Streambuf::traits_type; + + buffer& buffer_; + + public: + explicit formatbuf(buffer& buf) : buffer_(buf) {} + + protected: + // The put area is always empty. This makes the implementation simpler and has + // the advantage that the streambuf and the buffer are always in sync and + // sputc never writes into uninitialized memory. A disadvantage is that each + // call to sputc always results in a (virtual) call to overflow. There is no + // disadvantage here for sputn since this always results in a call to xsputn. + + auto overflow(int_type ch) -> int_type override { + if (!traits_type::eq_int_type(ch, traits_type::eof())) + buffer_.push_back(static_cast(ch)); + return ch; + } + + auto xsputn(const char_type* s, streamsize count) -> streamsize override { + buffer_.append(s, s + count); + return count; + } +}; // Generate a unique explicit instantion in every translation unit using a tag // type in an anonymous namespace. @@ -37,36 +68,40 @@ class file_access { template class file_access; auto get_file(std::filebuf&) -> FILE*; -#elif defined(_WIN32) && defined(_LIBCPP_VERSION) -template class file_access, - &std::__stdoutbuf::__file_>; -auto get_file(std::__stdoutbuf&) -> FILE*; #endif -inline bool write_ostream_unicode(std::ostream& os, fmt::string_view data) { +inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data) + -> bool { + FILE* f = nullptr; #if FMT_MSC_VERSION if (auto* buf = dynamic_cast(os.rdbuf())) - if (FILE* f = get_file(*buf)) return write_console(f, data); + f = get_file(*buf); + else + return false; #elif defined(_WIN32) && defined(__GLIBCXX__) auto* rdbuf = os.rdbuf(); - FILE* c_file; if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(rdbuf)) - c_file = sfbuf->file(); + f = sfbuf->file(); else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf*>(rdbuf)) - c_file = fbuf->file(); + f = fbuf->file(); else return false; - if (c_file) return write_console(c_file, data); -#elif defined(_WIN32) && defined(_LIBCPP_VERSION) - if (auto* buf = dynamic_cast*>(os.rdbuf())) - if (FILE* f = get_file(*buf)) return write_console(f, data); #else - ignore_unused(os, data); + ignore_unused(os, data, f); +#endif +#ifdef _WIN32 + if (f) { + int fd = _fileno(f); + if (_isatty(fd)) { + os.flush(); + return write_console(fd, data); + } + } #endif return false; } -inline bool write_ostream_unicode(std::wostream&, - fmt::basic_string_view) { +inline auto write_ostream_unicode(std::wostream&, + fmt::basic_string_view) -> bool { return false; } @@ -87,18 +122,19 @@ void write_buffer(std::basic_ostream -void format_value(buffer& buf, const T& value, - locale_ref loc = locale_ref()) { +void format_value(buffer& buf, const T& value) { auto&& format_buf = formatbuf>(buf); auto&& output = std::basic_ostream(&format_buf); #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) - if (loc) output.imbue(loc.get()); + output.imbue(std::locale::classic()); // The default is always unlocalized. #endif output << value; output.exceptions(std::ios_base::failbit | std::ios_base::badbit); } -template struct streamed_view { const T& value; }; +template struct streamed_view { + const T& value; +}; } // namespace detail @@ -111,7 +147,7 @@ struct basic_ostream_formatter : formatt auto format(const T& value, basic_format_context& ctx) const -> OutputIt { auto buffer = basic_memory_buffer(); - detail::format_value(buffer, value, ctx.locale()); + detail::format_value(buffer, value); return formatter, Char>::format( {buffer.data(), buffer.size()}, ctx); } @@ -140,7 +176,7 @@ struct formatter -auto streamed(const T& value) -> detail::streamed_view { +constexpr auto streamed(const T& value) -> detail::streamed_view { return {value}; } @@ -155,7 +191,7 @@ inline void vprint_directly(std::ostream } // namespace detail -FMT_MODULE_EXPORT template +FMT_EXPORT template void vprint(std::basic_ostream& os, basic_string_view> format_str, basic_format_args>> args) { @@ -174,7 +210,7 @@ void vprint(std::basic_ostream& os fmt::print(cerr, "Don't {}!", "panic"); \endrst */ -FMT_MODULE_EXPORT template +FMT_EXPORT template void print(std::ostream& os, format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); if (detail::is_utf8()) @@ -183,7 +219,7 @@ void print(std::ostream& os, format_stri detail::vprint_directly(os, fmt, vargs); } -FMT_MODULE_EXPORT +FMT_EXPORT template void print(std::wostream& os, basic_format_string...> fmt, @@ -191,12 +227,12 @@ void print(std::wostream& os, vprint(os, fmt, fmt::make_format_args>(args...)); } -FMT_MODULE_EXPORT template +FMT_EXPORT template void println(std::ostream& os, format_string fmt, T&&... args) { fmt::print(os, "{}\n", fmt::format(fmt, std::forward(args)...)); } -FMT_MODULE_EXPORT +FMT_EXPORT template void println(std::wostream& os, basic_format_string...> fmt,