2020-11-27 02:12:18 +08:00
|
|
|
// -*- C++ -*-
|
2021-11-18 05:25:01 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2020-11-27 02:12:18 +08:00
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_FORMAT
|
|
|
|
#define _LIBCPP_FORMAT
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
namespace std {
|
2020-12-05 18:45:21 +08:00
|
|
|
// [format.context], class template basic_format_context
|
2021-12-18 22:03:26 +08:00
|
|
|
template<class Out, class charT> class basic_format_context;
|
2020-12-05 18:45:21 +08:00
|
|
|
using format_context = basic_format_context<unspecified, char>;
|
|
|
|
using wformat_context = basic_format_context<unspecified, wchar_t>;
|
|
|
|
|
|
|
|
// [format.args], class template basic_format_args
|
2021-12-18 22:03:26 +08:00
|
|
|
template<class Context> class basic_format_args;
|
2020-12-05 18:45:21 +08:00
|
|
|
using format_args = basic_format_args<format_context>;
|
|
|
|
using wformat_args = basic_format_args<wformat_context>;
|
|
|
|
|
2021-10-02 18:38:46 +08:00
|
|
|
// [format.fmt.string], class template basic-format-string
|
|
|
|
template<class charT, class... Args>
|
|
|
|
struct basic-format-string; // exposition only
|
|
|
|
|
|
|
|
template<class... Args>
|
|
|
|
using format-string = // exposition only
|
|
|
|
basic-format-string<char, type_identity_t<Args>...>;
|
|
|
|
template<class... Args>
|
|
|
|
using wformat-string = // exposition only
|
|
|
|
basic-format-string<wchar_t, type_identity_t<Args>...>;
|
|
|
|
|
2020-12-19 20:52:07 +08:00
|
|
|
// [format.functions], formatting functions
|
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
string format(format-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
wstring format(wformat-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
string format(const locale& loc, format-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
wstring format(const locale& loc, wformat-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
string vformat(string_view fmt, format_args args);
|
|
|
|
wstring vformat(wstring_view fmt, wformat_args args);
|
|
|
|
string vformat(const locale& loc, string_view fmt, format_args args);
|
|
|
|
wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
|
|
|
|
|
|
|
|
template<class Out, class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
Out format_to(Out out, format-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out, class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
Out format_to(Out out, wformat-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out, class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
Out format_to(Out out, const locale& loc, format-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out, class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
Out format_to(Out out, const locale& loc, wformat-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
template<class Out>
|
2021-09-04 19:26:58 +08:00
|
|
|
Out vformat_to(Out out, string_view fmt, format_args args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out>
|
2021-09-04 19:26:58 +08:00
|
|
|
Out vformat_to(Out out, wstring_view fmt, wformat_args args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out>
|
|
|
|
Out vformat_to(Out out, const locale& loc, string_view fmt,
|
2021-09-04 19:26:58 +08:00
|
|
|
format_args char> args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out>
|
|
|
|
Out vformat_to(Out out, const locale& loc, wstring_view fmt,
|
2021-09-04 19:26:58 +08:00
|
|
|
wformat_args args);
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
template<class Out> struct format_to_n_result {
|
|
|
|
Out out;
|
|
|
|
iter_difference_t<Out> size;
|
|
|
|
};
|
2021-12-18 22:03:26 +08:00
|
|
|
template<class Out, class... Args>
|
2020-12-19 20:52:07 +08:00
|
|
|
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
|
2021-10-06 01:25:37 +08:00
|
|
|
format-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out, class... Args>
|
|
|
|
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
|
2021-10-06 01:25:37 +08:00
|
|
|
wformat-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out, class... Args>
|
|
|
|
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
|
2021-10-02 18:38:46 +08:00
|
|
|
const locale& loc, format-string<Args...> fmt,
|
2021-10-06 01:25:37 +08:00
|
|
|
Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class Out, class... Args>
|
|
|
|
format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
|
2021-10-02 18:38:46 +08:00
|
|
|
const locale& loc, wformat-string<Args...> fmt,
|
2021-10-06 01:25:37 +08:00
|
|
|
Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
size_t formatted_size(format-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
size_t formatted_size(wformat-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
size_t formatted_size(const locale& loc, format-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
template<class... Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
size_t formatted_size(const locale& loc, wformat-string<Args...> fmt, Args&&... args);
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
// [format.formatter], formatter
|
2021-12-18 22:03:26 +08:00
|
|
|
template<class T, class charT = char> struct formatter;
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2020-12-05 18:45:21 +08:00
|
|
|
// [format.parse.ctx], class template basic_format_parse_context
|
2021-12-18 22:03:26 +08:00
|
|
|
template<class charT> class basic_format_parse_context;
|
2020-12-05 18:45:21 +08:00
|
|
|
using format_parse_context = basic_format_parse_context<char>;
|
|
|
|
using wformat_parse_context = basic_format_parse_context<wchar_t>;
|
|
|
|
|
|
|
|
// [format.arguments], arguments
|
|
|
|
// [format.arg], class template basic_format_arg
|
2021-12-18 22:03:26 +08:00
|
|
|
template<class Context> class basic_format_arg;
|
2020-12-05 18:45:21 +08:00
|
|
|
|
|
|
|
template<class Visitor, class Context>
|
|
|
|
see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
|
|
|
|
|
|
|
|
// [format.arg.store], class template format-arg-store
|
2021-12-18 22:03:26 +08:00
|
|
|
template<class Context, class... Args> struct format-arg-store; // exposition only
|
2020-12-05 18:45:21 +08:00
|
|
|
|
|
|
|
template<class Context = format_context, class... Args>
|
|
|
|
format-arg-store<Context, Args...>
|
2021-10-06 01:25:37 +08:00
|
|
|
make_format_args(Args&&... args);
|
2020-12-05 18:45:21 +08:00
|
|
|
template<class... Args>
|
|
|
|
format-arg-store<wformat_context, Args...>
|
2021-10-06 01:25:37 +08:00
|
|
|
make_wformat_args(Args&&... args);
|
2020-12-05 18:45:21 +08:00
|
|
|
|
2020-11-27 02:12:18 +08:00
|
|
|
// [format.error], class format_error
|
2021-12-18 22:03:26 +08:00
|
|
|
class format_error;
|
2020-11-27 02:12:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2022-03-26 00:55:36 +08:00
|
|
|
#include <__assert> // all public C++ headers provide the assertion handler
|
2021-08-11 23:33:54 +08:00
|
|
|
// Make sure all feature-test macros are available.
|
2021-07-31 02:35:37 +08:00
|
|
|
#include <version>
|
2021-08-11 23:33:54 +08:00
|
|
|
// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
|
2021-07-31 02:35:37 +08:00
|
|
|
#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
|
|
|
|
2022-02-16 01:18:08 +08:00
|
|
|
#include <__algorithm/clamp.h>
|
2020-11-27 02:12:18 +08:00
|
|
|
#include <__config>
|
2020-12-19 20:52:07 +08:00
|
|
|
#include <__debug>
|
2021-09-05 03:05:23 +08:00
|
|
|
#include <__format/buffer.h>
|
2022-01-30 23:08:19 +08:00
|
|
|
#include <__format/concepts.h>
|
2021-09-26 21:47:42 +08:00
|
|
|
#include <__format/enable_insertable.h>
|
2020-12-05 18:45:21 +08:00
|
|
|
#include <__format/format_arg.h>
|
2021-10-03 19:11:53 +08:00
|
|
|
#include <__format/format_arg_store.h>
|
2020-12-05 18:45:21 +08:00
|
|
|
#include <__format/format_args.h>
|
|
|
|
#include <__format/format_context.h>
|
2021-04-25 23:58:03 +08:00
|
|
|
#include <__format/format_error.h>
|
[libc++][format] Adds integer formatter.
Implements the formatter for all fundamental integer types
(except `char`, `wchar_t`, and `bool`).
[format.formatter.spec]/2.3
For each charT, for each cv-unqualified arithmetic type ArithmeticT other
than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
```
template<> struct formatter<ArithmeticT, charT>;
```
This removes the stub implemented in D96664.
As an extension it adds partial support for 128-bit integer types.
Implements parts of:
- P0645 Text Formatting
- P1652 Printf corner cases in std::format
Completes:
- LWG-3248 #b, #B, #o, #x, and #X presentation types misformat negative numbers
Reviewed By: #libc, ldionne, vitaut
Differential Revision: https://reviews.llvm.org/D103433
2020-12-15 00:39:15 +08:00
|
|
|
#include <__format/format_fwd.h>
|
2021-04-26 00:23:42 +08:00
|
|
|
#include <__format/format_parse_context.h>
|
2020-12-19 20:52:07 +08:00
|
|
|
#include <__format/format_string.h>
|
2021-11-14 02:43:32 +08:00
|
|
|
#include <__format/format_to_n_result.h>
|
2020-12-19 20:52:07 +08:00
|
|
|
#include <__format/formatter.h>
|
2020-12-15 00:39:15 +08:00
|
|
|
#include <__format/formatter_bool.h>
|
2020-12-15 00:39:15 +08:00
|
|
|
#include <__format/formatter_char.h>
|
2020-12-15 00:39:15 +08:00
|
|
|
#include <__format/formatter_floating_point.h>
|
[libc++][format] Adds integer formatter.
Implements the formatter for all fundamental integer types
(except `char`, `wchar_t`, and `bool`).
[format.formatter.spec]/2.3
For each charT, for each cv-unqualified arithmetic type ArithmeticT other
than char, wchar_t, char8_t, char16_t, or char32_t, a specialization
```
template<> struct formatter<ArithmeticT, charT>;
```
This removes the stub implemented in D96664.
As an extension it adds partial support for 128-bit integer types.
Implements parts of:
- P0645 Text Formatting
- P1652 Printf corner cases in std::format
Completes:
- LWG-3248 #b, #B, #o, #x, and #X presentation types misformat negative numbers
Reviewed By: #libc, ldionne, vitaut
Differential Revision: https://reviews.llvm.org/D103433
2020-12-15 00:39:15 +08:00
|
|
|
#include <__format/formatter_integer.h>
|
2021-11-28 21:43:43 +08:00
|
|
|
#include <__format/formatter_pointer.h>
|
[libc++][format] Adds string formatter.
Implements the formatter for all string types.
[format.formatter.spec]/2.2
For each charT, the string type specializations
```
template<> struct formatter<charT*, charT>;
template<> struct formatter<const charT*, charT>;
template<size_t N> struct formatter<const charT[N], charT>;
template<class traits, class Allocator>
struct formatter<basic_string<charT, traits, Allocator>, charT>;
template<class traits>
struct formatter<basic_string_view<charT, traits>, charT>;
```
This removes the stub implemented in D96664.
Implements parts of:
- P0645 Text Formatting
- P1868 width: clarifying units of width and precision in std::format
Reviewed By: #libc, ldionne, vitaut
Differential Revision: https://reviews.llvm.org/D103425
2020-12-15 00:39:15 +08:00
|
|
|
#include <__format/formatter_string.h>
|
|
|
|
#include <__format/parser_std_format_spec.h>
|
2022-06-14 02:05:36 +08:00
|
|
|
#include <__iterator/back_insert_iterator.h>
|
2022-06-11 01:53:10 +08:00
|
|
|
#include <__iterator/incrementable_traits.h>
|
2020-12-19 20:52:07 +08:00
|
|
|
#include <__variant/monostate.h>
|
2020-12-05 18:45:21 +08:00
|
|
|
#include <array>
|
2020-12-19 20:52:07 +08:00
|
|
|
#include <concepts>
|
|
|
|
#include <string>
|
|
|
|
#include <string_view>
|
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
|
|
|
#include <locale>
|
|
|
|
#endif
|
2021-07-25 15:18:53 +08:00
|
|
|
|
2020-11-27 02:12:18 +08:00
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
2022-02-02 09:16:40 +08:00
|
|
|
# pragma GCC system_header
|
2020-11-27 02:12:18 +08:00
|
|
|
#endif
|
|
|
|
|
2020-12-05 18:45:21 +08:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
|
|
|
#if _LIBCPP_STD_VER > 17
|
|
|
|
|
2021-11-16 22:55:17 +08:00
|
|
|
// TODO FMT Move the implementation in this file to its own granular headers.
|
|
|
|
|
2020-12-05 18:45:21 +08:00
|
|
|
// TODO FMT Evaluate which templates should be external templates. This
|
|
|
|
// improves the efficiency of the header. However since the header is still
|
|
|
|
// under heavy development and not all classes are stable it makes no sense
|
|
|
|
// to do this optimization now.
|
|
|
|
|
|
|
|
using format_args = basic_format_args<format_context>;
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-05 18:45:21 +08:00
|
|
|
using wformat_args = basic_format_args<wformat_context>;
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-05 18:45:21 +08:00
|
|
|
|
|
|
|
template <class _Context = format_context, class... _Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) {
|
|
|
|
return _VSTD::__format_arg_store<_Context, _Args...>(__args...);
|
2020-12-05 18:45:21 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-05 18:45:21 +08:00
|
|
|
template <class... _Args>
|
2021-10-06 01:25:37 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) {
|
|
|
|
return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...);
|
2020-12-05 18:45:21 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
|
|
|
|
2020-12-19 20:52:07 +08:00
|
|
|
namespace __format {
|
|
|
|
|
2021-10-02 18:38:46 +08:00
|
|
|
/// Helper class parse and handle argument.
|
|
|
|
///
|
|
|
|
/// When parsing a handle which is not enabled the code is ill-formed.
|
|
|
|
/// This helper uses the parser of the appropriate formatter for the stored type.
|
|
|
|
template <class _CharT>
|
|
|
|
class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
|
|
|
|
public:
|
|
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
|
|
constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); }
|
|
|
|
|
|
|
|
template <class _Tp>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void __enable() {
|
|
|
|
__parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) {
|
|
|
|
formatter<_Tp, _CharT> __f;
|
|
|
|
__parse_ctx.advance_to(__f.parse(__parse_ctx));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Before calling __parse the proper handler needs to be set with __enable.
|
|
|
|
// The default handler isn't a core constant expression.
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()
|
|
|
|
: __parse_([](basic_format_parse_context<_CharT>&) { __throw_format_error("Not a handle"); }) {}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void (*__parse_)(basic_format_parse_context<_CharT>&);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Dummy format_context only providing the parts used during constant
|
|
|
|
// validation of the basic-format-string.
|
|
|
|
template <class _CharT>
|
|
|
|
struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context {
|
|
|
|
public:
|
|
|
|
using char_type = _CharT;
|
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(
|
|
|
|
const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)
|
|
|
|
: __args_(__args), __handles_(__handles), __size_(__size) {}
|
|
|
|
|
|
|
|
// During the compile-time validation nothing needs to be written.
|
|
|
|
// Therefore all operations of this iterator are a NOP.
|
|
|
|
struct iterator {
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }
|
|
|
|
};
|
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
|
|
|
|
if (__id >= __size_)
|
|
|
|
__throw_format_error("Argument index out of bounds");
|
|
|
|
return __args_[__id];
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {
|
|
|
|
if (__id >= __size_)
|
|
|
|
__throw_format_error("Argument index out of bounds");
|
|
|
|
return __handles_[__id];
|
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const __arg_t* __args_;
|
|
|
|
const __compile_time_handle<_CharT>* __handles_;
|
|
|
|
size_t __size_;
|
|
|
|
};
|
|
|
|
|
|
|
|
_LIBCPP_HIDE_FROM_ABI
|
|
|
|
constexpr void __compile_time_validate_integral(__arg_t __type) {
|
|
|
|
switch (__type) {
|
|
|
|
case __arg_t::__int:
|
|
|
|
case __arg_t::__long_long:
|
|
|
|
case __arg_t::__i128:
|
|
|
|
case __arg_t::__unsigned:
|
|
|
|
case __arg_t::__unsigned_long_long:
|
|
|
|
case __arg_t::__u128:
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
__throw_format_error("Argument isn't an integral type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// _HasPrecision does the formatter have a precision?
|
|
|
|
template <class _CharT, class _Tp, bool _HasPrecision = false>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void
|
|
|
|
__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx,
|
|
|
|
__compile_time_basic_format_context<_CharT>& __ctx) {
|
|
|
|
formatter<_Tp, _CharT> __formatter;
|
|
|
|
__parse_ctx.advance_to(__formatter.parse(__parse_ctx));
|
|
|
|
// [format.string.std]/7
|
|
|
|
// ... If the corresponding formatting argument is not of integral type, or
|
|
|
|
// its value is negative for precision or non-positive for width, an
|
|
|
|
// exception of type format_error is thrown.
|
|
|
|
//
|
|
|
|
// Validate whether the arguments are integrals.
|
[libc++][format] Improve string formatters
This changes the implementation of the formatter. Instead of inheriting
from a specialized parser all formatters will use the same generic
parser. This reduces the binary size.
The new parser contains some additional fields only used in the chrono
formatting. Since this doesn't change the size of the parser the fields
are in the generic parser. The parser is designed to fit in 128-bit,
making it cheap to pass by value.
The new format function is a const member function. This isn't required
by the Standard yet, but it will be after LWG-3636 is accepted.
Additionally P2286 adds a formattable concept which requires the member
function to be const qualified in C++23. This paper is likely to be
accepted in the 2022 July plenary.
Depends on D121530
NOTE parts of the code now contains duplicates for the current and new parser.
The intention is to remove the duplication in followup patches. A general
overview of the final code is available in D124620. That review however lacks a
bit of polish.
Most of the new code is based on the same algorithms used in the current code.
The final version of this code reduces the binary size by 17 KB for this example
code
```
int main() {
{
std::string_view sv{"hello world"};
std::format("{}{}|{}{}{}{}{}{}|{}{}{}{}{}{}|{}{}{}|{}{}|{}", true, '*',
(signed char)(42), (short)(42), (int)(42), (long)(42), (long long)(42), (__int128_t)(42),
(unsigned char)(42), (unsigned short)(42), (unsigned int)(42), (unsigned long)(42),
(unsigned long long)(42), (__uint128_t)(42),
(float)(42), (double)(42), (long double)(42),
"hello world", sv,
nullptr);
}
{
std::wstring_view sv{L"hello world"};
std::format(L"{}{}|{}{}{}{}{}{}|{}{}{}{}{}{}|{}{}{}|{}{}|{}", true, L'*',
(signed char)(42), (short)(42), (int)(42), (long)(42), (long long)(42), (__int128_t)(42),
(unsigned char)(42), (unsigned short)(42), (unsigned int)(42), (unsigned long)(42),
(unsigned long long)(42), (__uint128_t)(42),
(float)(42), (double)(42), (long double)(42),
L"hello world", sv,
nullptr);
}
}
```
Reviewed By: #libc, ldionne
Differential Revision: https://reviews.llvm.org/D125606
2021-12-29 01:48:04 +08:00
|
|
|
if constexpr (requires(formatter<_Tp, _CharT> __f) { __f.__width_needs_substitution(); }) {
|
|
|
|
// TODO FMT Remove this when parser v1 has been phased out.
|
|
|
|
if (__formatter.__width_needs_substitution())
|
|
|
|
__format::__compile_time_validate_integral(__ctx.arg(__formatter.__width));
|
|
|
|
|
|
|
|
if constexpr (_HasPrecision)
|
|
|
|
if (__formatter.__precision_needs_substitution())
|
|
|
|
__format::__compile_time_validate_integral(__ctx.arg(__formatter.__precision));
|
|
|
|
} else {
|
|
|
|
if (__formatter.__parser_.__width_as_arg_)
|
|
|
|
__format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_));
|
|
|
|
|
|
|
|
if constexpr (_HasPrecision)
|
|
|
|
if (__formatter.__parser_.__precision_as_arg_)
|
|
|
|
__format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_));
|
|
|
|
}
|
2021-10-02 18:38:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _CharT>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx,
|
|
|
|
__compile_time_basic_format_context<_CharT>& __ctx,
|
|
|
|
__arg_t __type) {
|
|
|
|
switch (__type) {
|
|
|
|
case __arg_t::__none:
|
|
|
|
__throw_format_error("Invalid argument");
|
|
|
|
case __arg_t::__boolean:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__char_type:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__int:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__long_long:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__i128:
|
|
|
|
# ifndef _LIBCPP_HAS_NO_INT128
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);
|
|
|
|
# else
|
|
|
|
__throw_format_error("Invalid argument");
|
|
|
|
# endif
|
|
|
|
return;
|
|
|
|
case __arg_t::__unsigned:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__unsigned_long_long:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__u128:
|
|
|
|
# ifndef _LIBCPP_HAS_NO_INT128
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);
|
|
|
|
# else
|
|
|
|
__throw_format_error("Invalid argument");
|
|
|
|
# endif
|
|
|
|
return;
|
|
|
|
case __arg_t::__float:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__double:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__long_double:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__const_char_type_ptr:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__string_view:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__ptr:
|
|
|
|
return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);
|
|
|
|
case __arg_t::__handle:
|
|
|
|
__throw_format_error("Handle should use __compile_time_validate_handle_argument");
|
|
|
|
}
|
|
|
|
__throw_format_error("Invalid argument");
|
|
|
|
}
|
|
|
|
|
2020-12-19 20:52:07 +08:00
|
|
|
template <class _CharT, class _ParseCtx, class _Ctx>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
|
2020-12-19 20:52:07 +08:00
|
|
|
__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
|
|
|
|
_ParseCtx& __parse_ctx, _Ctx& __ctx) {
|
|
|
|
__format::__parse_number_result __r =
|
|
|
|
__format::__parse_arg_id(__begin, __end, __parse_ctx);
|
|
|
|
|
2022-07-09 22:14:40 +08:00
|
|
|
bool __parse = *__r.__ptr == _CharT(':');
|
2020-12-19 20:52:07 +08:00
|
|
|
switch (*__r.__ptr) {
|
|
|
|
case _CharT(':'):
|
|
|
|
// The arg-id has a format-specifier, advance the input to the format-spec.
|
|
|
|
__parse_ctx.advance_to(__r.__ptr + 1);
|
|
|
|
break;
|
|
|
|
case _CharT('}'):
|
|
|
|
// The arg-id has no format-specifier.
|
|
|
|
__parse_ctx.advance_to(__r.__ptr);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
__throw_format_error(
|
|
|
|
"The replacement field arg-id should terminate at a ':' or '}'");
|
|
|
|
}
|
|
|
|
|
2021-10-02 18:38:46 +08:00
|
|
|
if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
|
|
|
|
__arg_t __type = __ctx.arg(__r.__value);
|
|
|
|
if (__type == __arg_t::__handle)
|
|
|
|
__ctx.__handle(__r.__value).__parse(__parse_ctx);
|
|
|
|
else
|
2022-07-09 22:14:40 +08:00
|
|
|
__format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
|
2021-10-02 18:38:46 +08:00
|
|
|
} else
|
|
|
|
_VSTD::visit_format_arg(
|
|
|
|
[&](auto __arg) {
|
|
|
|
if constexpr (same_as<decltype(__arg), monostate>)
|
|
|
|
__throw_format_error("Argument index out of bounds");
|
|
|
|
else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
|
|
|
|
__arg.format(__parse_ctx, __ctx);
|
|
|
|
else {
|
|
|
|
formatter<decltype(__arg), _CharT> __formatter;
|
2022-07-09 22:14:40 +08:00
|
|
|
if (__parse)
|
|
|
|
__parse_ctx.advance_to(__formatter.parse(__parse_ctx));
|
2021-10-02 18:38:46 +08:00
|
|
|
__ctx.advance_to(__formatter.format(__arg, __ctx));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
__ctx.arg(__r.__value));
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
__begin = __parse_ctx.begin();
|
|
|
|
if (__begin == __end || *__begin != _CharT('}'))
|
|
|
|
__throw_format_error("The replacement field misses a terminating '}'");
|
|
|
|
|
|
|
|
return ++__begin;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _ParseCtx, class _Ctx>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator
|
2020-12-19 20:52:07 +08:00
|
|
|
__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
|
|
|
|
using _CharT = typename _ParseCtx::char_type;
|
|
|
|
static_assert(same_as<typename _Ctx::char_type, _CharT>);
|
|
|
|
|
|
|
|
const _CharT* __begin = __parse_ctx.begin();
|
|
|
|
const _CharT* __end = __parse_ctx.end();
|
|
|
|
typename _Ctx::iterator __out_it = __ctx.out();
|
|
|
|
while (__begin != __end) {
|
|
|
|
switch (*__begin) {
|
|
|
|
case _CharT('{'):
|
|
|
|
++__begin;
|
|
|
|
if (__begin == __end)
|
|
|
|
__throw_format_error("The format string terminates at a '{'");
|
|
|
|
|
|
|
|
if (*__begin != _CharT('{')) [[likely]] {
|
|
|
|
__ctx.advance_to(_VSTD::move(__out_it));
|
|
|
|
__begin =
|
|
|
|
__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
|
|
|
|
__out_it = __ctx.out();
|
|
|
|
|
|
|
|
// The output is written and __begin points to the next character. So
|
|
|
|
// start the next iteration.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// The string is an escape character.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case _CharT('}'):
|
|
|
|
++__begin;
|
|
|
|
if (__begin == __end || *__begin != _CharT('}'))
|
|
|
|
__throw_format_error(
|
|
|
|
"The format string contains an invalid escape sequence");
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy the character to the output verbatim.
|
|
|
|
*__out_it++ = *__begin++;
|
|
|
|
}
|
|
|
|
return __out_it;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace __format
|
|
|
|
|
2021-10-02 18:38:46 +08:00
|
|
|
template <class _CharT, class... _Args>
|
|
|
|
struct _LIBCPP_TEMPLATE_VIS __basic_format_string {
|
|
|
|
basic_string_view<_CharT> __str_;
|
|
|
|
|
|
|
|
template <class _Tp>
|
|
|
|
requires convertible_to<const _Tp&, basic_string_view<_CharT>>
|
|
|
|
consteval __basic_format_string(const _Tp& __str) : __str_{__str} {
|
|
|
|
__format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
|
|
|
|
_Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
using _Context = __format::__compile_time_basic_format_context<_CharT>;
|
|
|
|
|
|
|
|
static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{
|
|
|
|
__format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};
|
|
|
|
|
|
|
|
// TODO FMT remove this work-around when the AIX ICE has been resolved.
|
|
|
|
# if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400
|
|
|
|
template <class _Tp>
|
|
|
|
static constexpr __format::__compile_time_handle<_CharT> __get_handle() {
|
|
|
|
__format::__compile_time_handle<_CharT> __handle;
|
|
|
|
if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
|
|
|
|
__handle.template __enable<_Tp>();
|
|
|
|
|
|
|
|
return __handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{
|
|
|
|
__get_handle<_Args>()...};
|
|
|
|
# else
|
|
|
|
static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {
|
|
|
|
using _Tp = remove_cvref_t<_Args>;
|
|
|
|
__format::__compile_time_handle<_CharT> __handle;
|
|
|
|
if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
|
|
|
|
__handle.template __enable<_Tp>();
|
|
|
|
|
|
|
|
return __handle;
|
|
|
|
}()...};
|
|
|
|
# endif
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class... _Args>
|
|
|
|
using __format_string_t = __basic_format_string<char, type_identity_t<_Args>...>;
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
|
|
|
template <class... _Args>
|
|
|
|
using __wformat_string_t = __basic_format_string<wchar_t, type_identity_t<_Args>...>;
|
|
|
|
#endif
|
|
|
|
|
2021-09-04 19:26:58 +08:00
|
|
|
template <class _OutIt, class _CharT, class _FormatOutIt>
|
2020-12-19 20:52:07 +08:00
|
|
|
requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
|
2021-09-04 19:26:58 +08:00
|
|
|
__vformat_to(
|
|
|
|
_OutIt __out_it, basic_string_view<_CharT> __fmt,
|
|
|
|
basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
|
|
|
|
if constexpr (same_as<_OutIt, _FormatOutIt>)
|
|
|
|
return _VSTD::__format::__vformat_to(
|
|
|
|
basic_format_parse_context{__fmt, __args.__size()},
|
|
|
|
_VSTD::__format_context_create(_VSTD::move(__out_it), __args));
|
|
|
|
else {
|
2021-09-05 03:05:23 +08:00
|
|
|
__format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
|
2021-09-04 19:26:58 +08:00
|
|
|
_VSTD::__format::__vformat_to(
|
|
|
|
basic_format_parse_context{__fmt, __args.__size()},
|
2021-09-05 03:05:23 +08:00
|
|
|
_VSTD::__format_context_create(__buffer.make_output_iterator(),
|
|
|
|
__args));
|
|
|
|
return _VSTD::move(__buffer).out();
|
2021-09-04 19:26:58 +08:00
|
|
|
}
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-09-26 23:04:53 +08:00
|
|
|
// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
|
|
|
|
// https://reviews.llvm.org/D110499#inline-1180704
|
|
|
|
// TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const char&> _OutIt>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
|
|
|
|
vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
|
2020-12-19 20:52:07 +08:00
|
|
|
return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
|
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const wchar_t&> _OutIt>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
|
|
|
|
vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
|
2020-12-19 20:52:07 +08:00
|
|
|
return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
|
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
template <output_iterator<const char&> _OutIt, class... _Args>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
|
2021-10-06 01:25:37 +08:00
|
|
|
format_to(_OutIt __out_it, __format_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_,
|
2021-09-04 19:26:58 +08:00
|
|
|
_VSTD::make_format_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const wchar_t&> _OutIt, class... _Args>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
|
2021-10-06 01:25:37 +08:00
|
|
|
format_to(_OutIt __out_it, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.__str_,
|
2021-09-04 19:26:58 +08:00
|
|
|
_VSTD::make_wformat_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
|
2020-12-19 20:52:07 +08:00
|
|
|
vformat(string_view __fmt, format_args __args) {
|
|
|
|
string __res;
|
|
|
|
_VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
|
|
|
|
return __res;
|
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
|
2020-12-19 20:52:07 +08:00
|
|
|
vformat(wstring_view __fmt, wformat_args __args) {
|
|
|
|
wstring __res;
|
|
|
|
_VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
|
|
|
|
return __res;
|
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
template <class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(__format_string_t<_Args...> __fmt,
|
2021-10-06 01:25:37 +08:00
|
|
|
_Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat(__fmt.__str_, _VSTD::make_format_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <class... _Args>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
|
2021-10-06 01:25:37 +08:00
|
|
|
format(__wformat_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat(__fmt.__str_, _VSTD::make_wformat_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2021-09-26 23:04:53 +08:00
|
|
|
template <class _Context, class _OutIt, class _CharT>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
|
|
|
|
basic_string_view<_CharT> __fmt,
|
|
|
|
basic_format_args<_Context> __args) {
|
|
|
|
__format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
|
|
|
|
_VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
|
|
|
|
_VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
|
|
|
|
return _VSTD::move(__buffer).result();
|
|
|
|
}
|
|
|
|
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const char&> _OutIt, class... _Args>
|
2021-09-26 23:04:53 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
|
2021-10-06 01:25:37 +08:00
|
|
|
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __format_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_format_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const wchar_t&> _OutIt, class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
|
|
|
|
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, __wformat_string_t<_Args...> __fmt,
|
2021-10-06 01:25:37 +08:00
|
|
|
_Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.__str_, _VSTD::make_wformat_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2021-09-26 22:48:25 +08:00
|
|
|
template <class _CharT>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
|
|
|
|
__format::__formatted_size_buffer<_CharT> __buffer;
|
|
|
|
_VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
|
|
|
|
_VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
|
|
|
|
return _VSTD::move(__buffer).result();
|
|
|
|
}
|
|
|
|
|
2020-12-19 20:52:07 +08:00
|
|
|
template <class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
|
2021-10-06 01:25:37 +08:00
|
|
|
formatted_size(__format_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)});
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
|
2021-10-06 01:25:37 +08:00
|
|
|
formatted_size(__wformat_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformatted_size(__fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)});
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
|
|
|
|
|
2021-09-04 19:26:58 +08:00
|
|
|
template <class _OutIt, class _CharT, class _FormatOutIt>
|
2020-12-19 20:52:07 +08:00
|
|
|
requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
|
2021-09-04 19:26:58 +08:00
|
|
|
__vformat_to(
|
|
|
|
_OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
|
|
|
|
basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
|
|
|
|
if constexpr (same_as<_OutIt, _FormatOutIt>)
|
|
|
|
return _VSTD::__format::__vformat_to(
|
|
|
|
basic_format_parse_context{__fmt, __args.__size()},
|
|
|
|
_VSTD::__format_context_create(_VSTD::move(__out_it), __args,
|
|
|
|
_VSTD::move(__loc)));
|
|
|
|
else {
|
2021-09-05 03:05:23 +08:00
|
|
|
__format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
|
2021-09-04 19:26:58 +08:00
|
|
|
_VSTD::__format::__vformat_to(
|
|
|
|
basic_format_parse_context{__fmt, __args.__size()},
|
2021-09-05 03:05:23 +08:00
|
|
|
_VSTD::__format_context_create(__buffer.make_output_iterator(),
|
|
|
|
__args, _VSTD::move(__loc)));
|
|
|
|
return _VSTD::move(__buffer).out();
|
2021-09-04 19:26:58 +08:00
|
|
|
}
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <output_iterator<const char&> _OutIt>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
|
|
|
|
_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
|
2020-12-19 20:52:07 +08:00
|
|
|
return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
|
|
|
|
__args);
|
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const wchar_t&> _OutIt>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
|
|
|
|
_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
|
2020-12-19 20:52:07 +08:00
|
|
|
return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
|
|
|
|
__args);
|
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
template <output_iterator<const char&> _OutIt, class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
|
2021-10-06 01:25:37 +08:00
|
|
|
format_to(_OutIt __out_it, locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_,
|
2021-09-04 19:26:58 +08:00
|
|
|
_VSTD::make_format_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const wchar_t&> _OutIt, class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
|
2021-10-06 01:25:37 +08:00
|
|
|
format_to(_OutIt __out_it, locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.__str_,
|
2021-09-04 19:26:58 +08:00
|
|
|
_VSTD::make_wformat_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
|
2020-12-19 20:52:07 +08:00
|
|
|
vformat(locale __loc, string_view __fmt, format_args __args) {
|
|
|
|
string __res;
|
|
|
|
_VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
|
|
|
|
__args);
|
|
|
|
return __res;
|
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
|
2020-12-19 20:52:07 +08:00
|
|
|
vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
|
|
|
|
wstring __res;
|
|
|
|
_VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
|
|
|
|
__args);
|
|
|
|
return __res;
|
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
|
|
|
template <class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc,
|
|
|
|
__format_string_t<_Args...> __fmt,
|
2021-10-06 01:25:37 +08:00
|
|
|
_Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_,
|
2020-12-19 20:52:07 +08:00
|
|
|
_VSTD::make_format_args(__args...));
|
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <class... _Args>
|
2021-09-04 19:26:58 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
|
2021-10-06 01:25:37 +08:00
|
|
|
format(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::vformat(_VSTD::move(__loc), __fmt.__str_,
|
2020-12-19 20:52:07 +08:00
|
|
|
_VSTD::make_wformat_args(__args...));
|
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2021-09-26 23:04:53 +08:00
|
|
|
template <class _Context, class _OutIt, class _CharT>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
|
|
|
|
locale __loc, basic_string_view<_CharT> __fmt,
|
|
|
|
basic_format_args<_Context> __args) {
|
|
|
|
__format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
|
|
|
|
_VSTD::__format::__vformat_to(
|
|
|
|
basic_format_parse_context{__fmt, __args.__size()},
|
|
|
|
_VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
|
|
|
|
return _VSTD::move(__buffer).result();
|
|
|
|
}
|
|
|
|
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const char&> _OutIt, class... _Args>
|
2021-09-26 23:04:53 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
|
2021-10-02 18:38:46 +08:00
|
|
|
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __format_string_t<_Args...> __fmt,
|
2021-10-06 01:25:37 +08:00
|
|
|
_Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_,
|
2021-09-26 23:04:53 +08:00
|
|
|
_VSTD::make_format_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <output_iterator<const wchar_t&> _OutIt, class... _Args>
|
2021-09-26 23:04:53 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
|
2021-10-02 18:38:46 +08:00
|
|
|
format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, __wformat_string_t<_Args...> __fmt,
|
2021-10-06 01:25:37 +08:00
|
|
|
_Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.__str_,
|
2021-09-26 23:04:53 +08:00
|
|
|
_VSTD::make_wformat_args(__args...));
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2021-09-26 22:48:25 +08:00
|
|
|
template <class _CharT>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
|
|
|
|
__format::__formatted_size_buffer<_CharT> __buffer;
|
|
|
|
_VSTD::__format::__vformat_to(
|
|
|
|
basic_format_parse_context{__fmt, __args.__size()},
|
|
|
|
_VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
|
|
|
|
return _VSTD::move(__buffer).result();
|
|
|
|
}
|
|
|
|
|
2020-12-19 20:52:07 +08:00
|
|
|
template <class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
|
2021-10-06 01:25:37 +08:00
|
|
|
formatted_size(locale __loc, __format_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_format_args(__args...)});
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
|
|
|
|
2021-08-24 03:32:36 +08:00
|
|
|
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
2020-12-19 20:52:07 +08:00
|
|
|
template <class... _Args>
|
2021-10-02 18:38:46 +08:00
|
|
|
_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
|
2021-10-06 01:25:37 +08:00
|
|
|
formatted_size(locale __loc, __wformat_string_t<_Args...> __fmt, _Args&&... __args) {
|
2021-10-02 18:38:46 +08:00
|
|
|
return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.__str_, basic_format_args{_VSTD::make_wformat_args(__args...)});
|
2020-12-19 20:52:07 +08:00
|
|
|
}
|
2021-08-24 03:32:36 +08:00
|
|
|
#endif
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2021-09-10 02:43:02 +08:00
|
|
|
#endif // _LIBCPP_HAS_NO_LOCALIZATION
|
2020-12-19 20:52:07 +08:00
|
|
|
|
2020-12-05 18:45:21 +08:00
|
|
|
#endif //_LIBCPP_STD_VER > 17
|
|
|
|
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
|
2021-07-31 02:35:37 +08:00
|
|
|
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
|
|
|
|
|
2020-11-27 02:12:18 +08:00
|
|
|
#endif // _LIBCPP_FORMAT
|