// <print> Print functions -*- C++ -*-

// Copyright The GNU Toolchain Authors.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file include/print
 *  This is a Standard C++ Library header.
 */

#ifndef _GLIBCXX_PRINT
#define _GLIBCXX_PRINT 1

#ifdef _GLIBCXX_SYSHDR
#pragma GCC system_header
#endif

#include <bits/requires_hosted.h> // for std::format

#define __glibcxx_want_print
#include <bits/version.h>

#ifdef __cpp_lib_print // C++ >= 23

#include <format>
#include <cstdio>
#include <cerrno>
#include <bits/functexcept.h>

#ifdef _WIN32
# include <system_error>
#endif

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  inline void
  vprint_nonunicode(FILE* __stream, string_view __fmt, format_args __args)
  {
    __format::_Str_sink<char> __buf;
    std::vformat_to(__buf.out(), __fmt, __args);
    auto __out = __buf.view();
    if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
      __throw_system_error(EIO);
  }

  inline void
  vprint_unicode(FILE* __stream, string_view __fmt, format_args __args)
  {
#if !defined(_WIN32) || defined(__CYGWIN__)
    // For most targets we don't need to do anything special to write
    // Unicode to a terminal.
    std::vprint_nonunicode(__stream, __fmt, __args);
#else
    __format::_Str_sink<char> __buf;
    std::vformat_to(__buf.out(), __fmt, __args);
    auto __out = __buf._M_span();

    void* __open_terminal(FILE*);
    error_code __write_to_terminal(void*, span<char>);
    // If stream refers to a terminal, write a native Unicode string to it.
    if (auto __term = __open_terminal(__stream))
      {
	string __out = std::vformat(__fmt, __args);
	error_code __e;
	if (!std::fflush(__stream))
	  {
	    __e = __write_to_terminal(__term, __out);
	    if (!__e)
	      return;
	    if (__e == std::make_error_code(errc::illegal_byte_sequence))
	      return;
	  }
	else
	  __e = error_code(errno, generic_category());
	_GLIBCXX_THROW_OR_ABORT(system_error(__e, "std::vprint_unicode"));
      }

    // Otherwise just write the string to the file as vprint_nonunicode does.
    if (std::fwrite(__out.data(), 1, __out.size(), __stream) != __out.size())
      __throw_system_error(EIO);
#endif
  }

  template<typename... _Args>
    inline void
    print(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args)
    {
      auto __fmtargs = std::make_format_args(__args...);
      if constexpr (__unicode::__literal_encoding_is_utf8())
	std::vprint_unicode(__stream, __fmt.get(), __fmtargs);
      else
	std::vprint_nonunicode(__stream, __fmt.get(), __fmtargs);
    }

  template<typename... _Args>
    inline void
    print(format_string<_Args...> __fmt, _Args&&... __args)
    { std::print(stdout, __fmt, std::forward<_Args>(__args)...); }

  template<typename... _Args>
    inline void
    println(FILE* __stream, format_string<_Args...> __fmt, _Args&&... __args)
    {
      std::print(__stream, "{}\n",
		 std::format(__fmt, std::forward<_Args>(__args)...));
    }

  template<typename... _Args>
    inline void
    println(format_string<_Args...> __fmt, _Args&&... __args)
    { std::println(stdout, __fmt, std::forward<_Args>(__args)...); }

  inline void
  vprint_unicode(string_view __fmt, format_args __args)
  { std::vprint_unicode(stdout, __fmt, __args); }

  inline void
  vprint_nonunicode(string_view __fmt, format_args __args)
  { std::vprint_nonunicode(stdout, __fmt, __args); }

  // Defined for C++26, supported as an extension to C++23.
  inline void println(FILE* __stream)
  {
#if defined(_WIN32) && !defined(__CYGWIN__)
    if constexpr (__unicode::__literal_encoding_is_utf8())
      std::vprint_unicode(__stream, "\n", std::make_format_args());
    else
#endif
      if (std::putc('\n', __stream) == EOF)
	__throw_system_error(EIO);
  }

  inline void println() { std::println(stdout); }

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // __cpp_lib_print
#endif // _GLIBCXX_PRINT
