brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.4 KiB · 873265b Raw
723 lines · c
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS11#define _LIBCPP___FORMAT_FORMAT_FUNCTIONS12 13#include <__algorithm/clamp.h>14#include <__algorithm/ranges_find_first_of.h>15#include <__chrono/statically_widen.h>16#include <__concepts/convertible_to.h>17#include <__concepts/same_as.h>18#include <__config>19#include <__format/buffer.h>20#include <__format/format_arg.h>21#include <__format/format_arg_store.h>22#include <__format/format_args.h>23#include <__format/format_context.h>24#include <__format/format_error.h>25#include <__format/format_parse_context.h>26#include <__format/format_string.h>27#include <__format/format_to_n_result.h>28#include <__format/formatter.h>29#include <__format/formatter_bool.h>30#include <__format/formatter_char.h>31#include <__format/formatter_floating_point.h>32#include <__format/formatter_integer.h>33#include <__format/formatter_pointer.h>34#include <__format/formatter_string.h>35#include <__format/parser_std_format_spec.h>36#include <__iterator/concepts.h>37#include <__iterator/incrementable_traits.h>38#include <__iterator/iterator_traits.h> // iter_value_t39#include <__variant/monostate.h>40#include <array>41#include <optional>42#include <string>43#include <string_view>44 45#if _LIBCPP_HAS_LOCALIZATION46#  include <__locale>47#endif48 49#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)50#  pragma GCC system_header51#endif52 53_LIBCPP_PUSH_MACROS54#include <__undef_macros>55 56_LIBCPP_BEGIN_NAMESPACE_STD57 58#if _LIBCPP_STD_VER >= 2059 60// TODO FMT Evaluate which templates should be external templates. This61// improves the efficiency of the header. However since the header is still62// under heavy development and not all classes are stable it makes no sense63// to do this optimization now.64 65using format_args = basic_format_args<format_context>;66#  if _LIBCPP_HAS_WIDE_CHARACTERS67using wformat_args = basic_format_args<wformat_context>;68#  endif69 70template <class _Context = format_context, class... _Args>71[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) {72  return std::__format_arg_store<_Context, _Args...>(__args...);73}74 75#  if _LIBCPP_HAS_WIDE_CHARACTERS76template <class... _Args>77[[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&... __args) {78  return std::__format_arg_store<wformat_context, _Args...>(__args...);79}80#  endif81 82namespace __format {83 84/// Helper class parse and handle argument.85///86/// When parsing a handle which is not enabled the code is ill-formed.87/// This helper uses the parser of the appropriate formatter for the stored type.88template <class _CharT>89class __compile_time_handle {90public:91  template <class _ParseContext>92  _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const {93    __parse_(__ctx);94  }95 96  template <class _Tp>97  _LIBCPP_HIDE_FROM_ABI constexpr void __enable() {98    __parse_ = [](basic_format_parse_context<_CharT>& __ctx) {99      formatter<_Tp, _CharT> __f;100      __ctx.advance_to(__f.parse(__ctx));101    };102  }103 104  // Before calling __parse the proper handler needs to be set with __enable.105  // The default handler isn't a core constant expression.106  _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()107      : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {}108 109private:110  void (*__parse_)(basic_format_parse_context<_CharT>&);111};112 113// Dummy format_context only providing the parts used during constant114// validation of the basic_format_string.115template <class _CharT>116struct __compile_time_basic_format_context {117public:118  using char_type = _CharT;119 120  _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(121      const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)122      : __args_(__args), __handles_(__handles), __size_(__size) {}123 124  // During the compile-time validation nothing needs to be written.125  // Therefore all operations of this iterator are a NOP.126  struct iterator {127    _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }128    _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }129    _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }130  };131 132  _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {133    if (__id >= __size_)134      std::__throw_format_error("The argument index value is too large for the number of arguments supplied");135    return __args_[__id];136  }137 138  _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {139    if (__id >= __size_)140      std::__throw_format_error("The argument index value is too large for the number of arguments supplied");141    return __handles_[__id];142  }143 144  _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }145  _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}146 147private:148  const __arg_t* __args_;149  const __compile_time_handle<_CharT>* __handles_;150  size_t __size_;151};152 153// [format.string.std]/8154// If { arg-idopt } is used in a width or precision, the value of the155// corresponding formatting argument is used in its place. If the156// corresponding formatting argument is not of standard signed or unsigned157// integer type, or its value is negative for precision or non-positive for158// width, an exception of type format_error is thrown.159//160// _HasPrecision does the formatter have a precision?161template <class _CharT, class _Tp, bool _HasPrecision = false>162_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument(163    basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) {164  auto __validate_type = [](__arg_t __type) {165    // LWG3720 originally allowed "signed or unsigned integer types", however166    // the final version explicitly changed it to "*standard* signed or unsigned167    // integer types". It's trivial to use 128-bit integrals in libc++'s168    // implementation, but other implementations may not implement it.169    // (Using a width or precision, that does not fit in 64-bits, sounds very170    // unlikely in real world code.)171    switch (__type) {172    case __arg_t::__int:173    case __arg_t::__long_long:174    case __arg_t::__unsigned:175    case __arg_t::__unsigned_long_long:176      return;177 178    default:179      std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type");180    }181  };182 183  formatter<_Tp, _CharT> __formatter;184  __parse_ctx.advance_to(__formatter.parse(__parse_ctx));185  if (__formatter.__parser_.__width_as_arg_)186    __validate_type(__ctx.arg(__formatter.__parser_.__width_));187 188  if constexpr (_HasPrecision)189    if (__formatter.__parser_.__precision_as_arg_)190      __validate_type(__ctx.arg(__formatter.__parser_.__precision_));191}192 193// This function is not user facing, so it can directly use the non-standard types of the "variant".194template <class _CharT>195_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(196    basic_format_parse_context<_CharT>& __parse_ctx,197    __compile_time_basic_format_context<_CharT>& __ctx,198    __arg_t __type) {199  switch (__type) {200  case __arg_t::__none:201    std::__throw_format_error("Invalid argument");202  case __arg_t::__boolean:203    return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);204  case __arg_t::__char_type:205    return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);206  case __arg_t::__int:207    return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);208  case __arg_t::__long_long:209    return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);210  case __arg_t::__i128:211#  if _LIBCPP_HAS_INT128212    return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);213#  else214    std::__throw_format_error("Invalid argument");215#  endif216    return;217  case __arg_t::__unsigned:218    return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);219  case __arg_t::__unsigned_long_long:220    return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);221  case __arg_t::__u128:222#  if _LIBCPP_HAS_INT128223    return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);224#  else225    std::__throw_format_error("Invalid argument");226#  endif227    return;228  case __arg_t::__float:229    return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);230  case __arg_t::__double:231    return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);232  case __arg_t::__long_double:233    return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);234  case __arg_t::__const_char_type_ptr:235    return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);236  case __arg_t::__string_view:237    return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);238  case __arg_t::__ptr:239    return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);240  case __arg_t::__handle:241    std::__throw_format_error("Handle should use __compile_time_validate_handle_argument");242  }243  std::__throw_format_error("Invalid argument");244}245 246template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx>247_LIBCPP_HIDE_FROM_ABI constexpr _Iterator248__handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) {249  using _CharT                        = iter_value_t<_Iterator>;250  __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);251 252  if (__r.__last == __end)253    std::__throw_format_error("The argument index should end with a ':' or a '}'");254 255  bool __parse = *__r.__last == _CharT(':');256  switch (*__r.__last) {257  case _CharT(':'):258    // The arg-id has a format-specifier, advance the input to the format-spec.259    __parse_ctx.advance_to(__r.__last + 1);260    break;261  case _CharT('}'):262    // The arg-id has no format-specifier.263    __parse_ctx.advance_to(__r.__last);264    break;265  default:266    std::__throw_format_error("The argument index should end with a ':' or a '}'");267  }268 269  if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {270    __arg_t __type = __ctx.arg(__r.__value);271    if (__type == __arg_t::__none)272      std::__throw_format_error("The argument index value is too large for the number of arguments supplied");273    else if (__type == __arg_t::__handle)274      __ctx.__handle(__r.__value).__parse(__parse_ctx);275    else if (__parse)276      __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);277  } else278    std::__visit_format_arg(279        [&](auto __arg) {280          if constexpr (same_as<decltype(__arg), monostate>)281            std::__throw_format_error("The argument index value is too large for the number of arguments supplied");282          else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)283            __arg.format(__parse_ctx, __ctx);284          else {285            formatter<decltype(__arg), _CharT> __formatter;286            if (__parse)287              __parse_ctx.advance_to(__formatter.parse(__parse_ctx));288            __ctx.advance_to(__formatter.format(__arg, __ctx));289          }290        },291        __ctx.arg(__r.__value));292 293  __begin = __parse_ctx.begin();294  if (__begin == __end || *__begin != _CharT('}'))295    std::__throw_format_error("The replacement field misses a terminating '}'");296 297  return ++__begin;298}299 300template <class _ParseCtx, class _Ctx>301_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {302  using _CharT = typename _ParseCtx::char_type;303  static_assert(same_as<typename _Ctx::char_type, _CharT>);304 305  auto __begin                     = __parse_ctx.begin();306  auto __end                       = __parse_ctx.end();307  typename _Ctx::iterator __out_it = __ctx.out();308  while (__begin != __end) {309    switch (*__begin) {310    case _CharT('{'):311      ++__begin;312      if (__begin == __end)313        std::__throw_format_error("The format string terminates at a '{'");314 315      if (*__begin != _CharT('{')) [[likely]] {316        __ctx.advance_to(std::move(__out_it));317        __begin  = __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);318        __out_it = __ctx.out();319 320        // The output is written and __begin points to the next character. So321        // start the next iteration.322        continue;323      }324      // The string is an escape character.325      break;326 327    case _CharT('}'):328      ++__begin;329      if (__begin == __end || *__begin != _CharT('}'))330        std::__throw_format_error("The format string contains an invalid escape sequence");331 332      break;333    }334 335    // Copy the character to the output verbatim.336    *__out_it++ = *__begin++;337  }338  return __out_it;339}340 341} // namespace __format342 343#  if _LIBCPP_STD_VER >= 26344template <class _CharT>345struct __runtime_format_string {346private:347  basic_string_view<_CharT> __str_;348 349  template <class _Cp, class... _Args>350  friend struct basic_format_string;351 352public:353  _LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {}354 355  __runtime_format_string(const __runtime_format_string&)            = delete;356  __runtime_format_string& operator=(const __runtime_format_string&) = delete;357};358 359_LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; }360#    if _LIBCPP_HAS_WIDE_CHARACTERS361_LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept {362  return __fmt;363}364#    endif365#  endif // _LIBCPP_STD_VER >= 26366 367template <class _CharT, class... _Args>368struct basic_format_string {369  template <class _Tp>370    requires convertible_to<const _Tp&, basic_string_view<_CharT>>371  consteval basic_format_string(const _Tp& __str) : __str_{__str} {372    __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},373                           _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});374  }375 376  _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; }377#  if _LIBCPP_STD_VER >= 26378  _LIBCPP_HIDE_FROM_ABI basic_format_string(__runtime_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {}379#  endif380 381private:382  basic_string_view<_CharT> __str_;383 384  using _Context _LIBCPP_NODEBUG = __format::__compile_time_basic_format_context<_CharT>;385 386  static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{387      __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};388 389  static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {390    using _Tp = remove_cvref_t<_Args>;391    __format::__compile_time_handle<_CharT> __handle;392    if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)393      __handle.template __enable<_Tp>();394 395    return __handle;396  }()...};397};398 399template <class... _Args>400using format_string = basic_format_string<char, type_identity_t<_Args>...>;401 402#  if _LIBCPP_HAS_WIDE_CHARACTERS403template <class... _Args>404using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>;405#  endif406 407template <class _OutIt, class _CharT, class _FormatOutIt>408  requires(output_iterator<_OutIt, const _CharT&>)409_LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it,410                                          basic_string_view<_CharT> __fmt,411                                          basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {412  if constexpr (same_as<_OutIt, _FormatOutIt>)413    return std::__format::__vformat_to(414        basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args));415  else {416    typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)};417    std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},418                                std::__format_context_create(__buffer.__make_output_iterator(), __args));419    return std::move(__buffer).__out_it();420  }421}422 423// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining424// https://reviews.llvm.org/D110499#inline-1180704425// TODO FMT Evaluate whether we want to file a Clang bug report regarding this.426template <output_iterator<const char&> _OutIt>427_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {428  return std::__vformat_to(std::move(__out_it), __fmt, __args);429}430 431#  if _LIBCPP_HAS_WIDE_CHARACTERS432template <output_iterator<const wchar_t&> _OutIt>433_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt434vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {435  return std::__vformat_to(std::move(__out_it), __fmt, __args);436}437#  endif438 439template <output_iterator<const char&> _OutIt, class... _Args>440_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt441format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) {442  return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_format_args(__args...));443}444 445#  if _LIBCPP_HAS_WIDE_CHARACTERS446template <output_iterator<const wchar_t&> _OutIt, class... _Args>447_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt448format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {449  return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_wformat_args(__args...));450}451#  endif452 453// Try constant folding the format string instead of going through the whole formatting machinery. If there is no454// constant folding no extra code should be emitted (with optimizations enabled) and the function returns nullopt. When455// constant folding is successful, the formatting is performed and the resulting string is returned.456namespace __format {457template <class _CharT>458[[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<basic_string<_CharT>> __try_constant_folding(459    basic_string_view<_CharT> __fmt,460    basic_format_args<basic_format_context<back_insert_iterator<__format::__output_buffer<_CharT>>, _CharT>> __args) {461  // Fold strings not containing '{' or '}' to just return the string462  if (bool __is_identity = [&] [[__gnu__::__pure__]] // Make sure the compiler knows this call can be eliminated463      { return std::ranges::find_first_of(__fmt, array{'{', '}'}) == __fmt.end(); }();464      __builtin_constant_p(__is_identity) && __is_identity)465    return basic_string<_CharT>{__fmt};466 467  // Fold '{}' to the appropriate conversion function468  if (auto __only_first_arg = __fmt == _LIBCPP_STATICALLY_WIDEN(_CharT, "{}");469      __builtin_constant_p(__only_first_arg) && __only_first_arg) {470    if (auto __arg = __args.get(0); __builtin_constant_p(__arg.__type_)) {471      return std::__visit_format_arg(472          []<class _Tp>(_Tp&& __argument) -> optional<basic_string<_CharT>> {473            if constexpr (is_same_v<remove_cvref_t<_Tp>, basic_string_view<_CharT>>) {474              return basic_string<_CharT>{__argument};475            } else {476              return nullopt;477            }478          },479          __arg);480    }481  }482 483  return nullopt;484}485} // namespace __format486 487// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup488// fires too eagerly, see http://llvm.org/PR61563.489template <class = void>490[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) {491  auto __result = __format::__try_constant_folding(__fmt, __args);492  if (__result.has_value())493    return *std::move(__result);494  __format::__allocating_buffer<char> __buffer;495  std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args);496  return string{__buffer.__view()};497}498 499#  if _LIBCPP_HAS_WIDE_CHARACTERS500// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup501// fires too eagerly, see http://llvm.org/PR61563.502template <class = void>503[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring504vformat(wstring_view __fmt, wformat_args __args) {505  auto __result = __format::__try_constant_folding(__fmt, __args);506  if (__result.has_value())507    return *std::move(__result);508  __format::__allocating_buffer<wchar_t> __buffer;509  std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args);510  return wstring{__buffer.__view()};511}512#  endif513 514template <class... _Args>515[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string516format(format_string<_Args...> __fmt, _Args&&... __args) {517  return std::vformat(__fmt.get(), std::make_format_args(__args...));518}519 520#  if _LIBCPP_HAS_WIDE_CHARACTERS521template <class... _Args>522[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring523format(wformat_string<_Args...> __fmt, _Args&&... __args) {524  return std::vformat(__fmt.get(), std::make_wformat_args(__args...));525}526#  endif527 528template <class _Context, class _OutIt, class _CharT>529_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>530__vformat_to_n(_OutIt __out_it,531               iter_difference_t<_OutIt> __n,532               basic_string_view<_CharT> __fmt,533               basic_format_args<_Context> __args) {534  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n};535  std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},536                              std::__format_context_create(__buffer.__make_output_iterator(), __args));537  return std::move(__buffer).__result();538}539 540template <output_iterator<const char&> _OutIt, class... _Args>541_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>542format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) {543  return std::__vformat_to_n<format_context>(std::move(__out_it), __n, __fmt.get(), std::make_format_args(__args...));544}545 546#  if _LIBCPP_HAS_WIDE_CHARACTERS547template <output_iterator<const wchar_t&> _OutIt, class... _Args>548_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>549format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) {550  return std::__vformat_to_n<wformat_context>(std::move(__out_it), __n, __fmt.get(), std::make_wformat_args(__args...));551}552#  endif553 554template <class _CharT>555_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {556  __format::__formatted_size_buffer<_CharT> __buffer;557  std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},558                              std::__format_context_create(__buffer.__make_output_iterator(), __args));559  return std::move(__buffer).__result();560}561 562template <class... _Args>563[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t564formatted_size(format_string<_Args...> __fmt, _Args&&... __args) {565  return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)});566}567 568#  if _LIBCPP_HAS_WIDE_CHARACTERS569template <class... _Args>570[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t571formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) {572  return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)});573}574#  endif575 576#  if _LIBCPP_HAS_LOCALIZATION577 578template <class _OutIt, class _CharT, class _FormatOutIt>579  requires(output_iterator<_OutIt, const _CharT&>)580_LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(581    _OutIt __out_it,582    locale __loc,583    basic_string_view<_CharT> __fmt,584    basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {585  if constexpr (same_as<_OutIt, _FormatOutIt>)586    return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},587                                       std::__format_context_create(std::move(__out_it), __args, std::move(__loc)));588  else {589    typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)};590    std::__format::__vformat_to(591        basic_format_parse_context{__fmt, __args.__size()},592        std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));593    return std::move(__buffer).__out_it();594  }595}596 597template <output_iterator<const char&> _OutIt>598_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt599vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {600  return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args);601}602 603#    if _LIBCPP_HAS_WIDE_CHARACTERS604template <output_iterator<const wchar_t&> _OutIt>605_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt606vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {607  return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args);608}609#    endif610 611template <output_iterator<const char&> _OutIt, class... _Args>612_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt613format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {614  return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_format_args(__args...));615}616 617#    if _LIBCPP_HAS_WIDE_CHARACTERS618template <output_iterator<const wchar_t&> _OutIt, class... _Args>619_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt620format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {621  return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));622}623#    endif624 625// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup626// fires too eagerly, see http://llvm.org/PR61563.627template <class = void>628[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string629vformat(locale __loc, string_view __fmt, format_args __args) {630  __format::__allocating_buffer<char> __buffer;631  std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args);632  return string{__buffer.__view()};633}634 635#    if _LIBCPP_HAS_WIDE_CHARACTERS636// TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup637// fires too eagerly, see http://llvm.org/PR61563.638template <class = void>639[[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring640vformat(locale __loc, wstring_view __fmt, wformat_args __args) {641  __format::__allocating_buffer<wchar_t> __buffer;642  std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args);643  return wstring{__buffer.__view()};644}645#    endif646 647template <class... _Args>648[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string649format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {650  return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...));651}652 653#    if _LIBCPP_HAS_WIDE_CHARACTERS654template <class... _Args>655[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring656format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {657  return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));658}659#    endif660 661template <class _Context, class _OutIt, class _CharT>662_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(663    _OutIt __out_it,664    iter_difference_t<_OutIt> __n,665    locale __loc,666    basic_string_view<_CharT> __fmt,667    basic_format_args<_Context> __args) {668  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n};669  std::__format::__vformat_to(670      basic_format_parse_context{__fmt, __args.__size()},671      std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));672  return std::move(__buffer).__result();673}674 675template <output_iterator<const char&> _OutIt, class... _Args>676_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(677    _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {678  return std::__vformat_to_n<format_context>(679      std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_format_args(__args...));680}681 682#    if _LIBCPP_HAS_WIDE_CHARACTERS683template <output_iterator<const wchar_t&> _OutIt, class... _Args>684_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(685    _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {686  return std::__vformat_to_n<wformat_context>(687      std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));688}689#    endif690 691template <class _CharT>692_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {693  __format::__formatted_size_buffer<_CharT> __buffer;694  std::__format::__vformat_to(695      basic_format_parse_context{__fmt, __args.__size()},696      std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));697  return std::move(__buffer).__result();698}699 700template <class... _Args>701[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t702formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {703  return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)});704}705 706#    if _LIBCPP_HAS_WIDE_CHARACTERS707template <class... _Args>708[[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t709formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {710  return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)});711}712#    endif713 714#  endif // _LIBCPP_HAS_LOCALIZATION715 716#endif // _LIBCPP_STD_VER >= 20717 718_LIBCPP_END_NAMESPACE_STD719 720_LIBCPP_POP_MACROS721 722#endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS723