diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -294,6 +294,7 @@ __format/format_args.h __format/format_context.h __format/format_error.h + __format/format_functions.h __format/format_fwd.h __format/format_parse_context.h __format/format_string.h diff --git a/libcxx/include/format b/libcxx/include/__format/format_functions.h copy from libcxx/include/format copy to libcxx/include/__format/format_functions.h --- a/libcxx/include/format +++ b/libcxx/include/__format/format_functions.h @@ -7,152 +7,25 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP_FORMAT -#define _LIBCPP_FORMAT +#ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS +#define _LIBCPP___FORMAT_FORMAT_FUNCTIONS -/* - -namespace std { - // [format.context], class template basic_format_context - template class basic_format_context; - using format_context = basic_format_context; - using wformat_context = basic_format_context; - - // [format.args], class template basic_format_args - template class basic_format_args; - using format_args = basic_format_args; - using wformat_args = basic_format_args; - - // [format.fmt.string], class template basic_format_string - template - struct basic_format_string { // since C++23, exposition only before C++23 - private: - basic_string_view str; // exposition only - - public: - template consteval basic_format_string(const T& s); - - constexpr basic_string_view get() const noexcept { return str; } - }; - template - using format_string = // since C++23, exposition only before C++23 - basic_format_string...>; - template - using wformat_string = // since C++23, exposition only before C++23 - basic_format_string...>; - - // [format.functions], formatting functions - template - string format(format-string fmt, Args&&... args); - template - wstring format(wformat-string fmt, Args&&... args); - template - string format(const locale& loc, format-string fmt, Args&&... args); - template - wstring format(const locale& loc, wformat-string fmt, Args&&... args); - - 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 - Out format_to(Out out, format-string fmt, Args&&... args); - template - Out format_to(Out out, wformat-string fmt, Args&&... args); - template - Out format_to(Out out, const locale& loc, format-string fmt, Args&&... args); - template - Out format_to(Out out, const locale& loc, wformat-string fmt, Args&&... args); - - template - Out vformat_to(Out out, string_view fmt, format_args args); - template - Out vformat_to(Out out, wstring_view fmt, wformat_args args); - template - Out vformat_to(Out out, const locale& loc, string_view fmt, - format_args char> args); - template - Out vformat_to(Out out, const locale& loc, wstring_view fmt, - wformat_args args); - - template struct format_to_n_result { - Out out; - iter_difference_t size; - }; - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - format-string fmt, Args&&... args); - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - wformat-string fmt, Args&&... args); - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - const locale& loc, format-string fmt, - Args&&... args); - template - format_to_n_result format_to_n(Out out, iter_difference_t n, - const locale& loc, wformat-string fmt, - Args&&... args); - - template - size_t formatted_size(format-string fmt, Args&&... args); - template - size_t formatted_size(wformat-string fmt, Args&&... args); - template - size_t formatted_size(const locale& loc, format-string fmt, Args&&... args); - template - size_t formatted_size(const locale& loc, wformat-string fmt, Args&&... args); - - // [format.formatter], formatter - template struct formatter; - - // [format.parse.ctx], class template basic_format_parse_context - template class basic_format_parse_context; - using format_parse_context = basic_format_parse_context; - using wformat_parse_context = basic_format_parse_context; - - // [format.arguments], arguments - // [format.arg], class template basic_format_arg - template class basic_format_arg; - - template - see below visit_format_arg(Visitor&& vis, basic_format_arg arg); - - // [format.arg.store], class template format-arg-store - template struct format-arg-store; // exposition only - - template - format-arg-store - make_format_args(Args&&... args); - template - format-arg-store - make_wformat_args(Args&&... args); - - // [format.error], class format_error - class format_error; -} - -*/ - -#include <__assert> // all public C++ headers provide the assertion handler -// Make sure all feature-test macros are available. +// TODO FMT This is added to fix Apple back-deployment. #include -// Enable the contents of the header only when libc++ was built with experimental features enabled. #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) #include <__algorithm/clamp.h> +#include <__availability> +#include <__concepts/convertible_to.h> +#include <__concepts/same_as.h> #include <__config> #include <__debug> #include <__format/buffer.h> -#include <__format/concepts.h> -#include <__format/enable_insertable.h> #include <__format/format_arg.h> #include <__format/format_arg_store.h> #include <__format/format_args.h> #include <__format/format_context.h> #include <__format/format_error.h> -#include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__format/format_string.h> #include <__format/format_to_n_result.h> @@ -164,15 +37,12 @@ #include <__format/formatter_pointer.h> #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> -#include <__format/unicode.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/incrementable_traits.h> #include <__variant/monostate.h> #include -#include #include #include -#include #ifndef _LIBCPP_HAS_NO_LOCALIZATION #include @@ -186,8 +56,6 @@ #if _LIBCPP_STD_VER > 17 -// TODO FMT Move the implementation in this file to its own granular headers. - // 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 @@ -790,10 +658,11 @@ #endif // _LIBCPP_HAS_NO_LOCALIZATION + #endif //_LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) -#endif // _LIBCPP_FORMAT +#endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS diff --git a/libcxx/include/format b/libcxx/include/format --- a/libcxx/include/format +++ b/libcxx/include/format @@ -141,9 +141,7 @@ // Enable the contents of the header only when libc++ was built with experimental features enabled. #if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) -#include <__algorithm/clamp.h> #include <__config> -#include <__debug> #include <__format/buffer.h> #include <__format/concepts.h> #include <__format/enable_insertable.h> @@ -152,6 +150,7 @@ #include <__format/format_args.h> #include <__format/format_context.h> #include <__format/format_error.h> +#include <__format/format_functions.h> #include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__format/format_string.h> @@ -165,635 +164,11 @@ #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> #include <__format/unicode.h> -#include <__iterator/back_insert_iterator.h> -#include <__iterator/incrementable_traits.h> -#include <__variant/monostate.h> -#include -#include -#include -#include -#include - -#ifndef _LIBCPP_HAS_NO_LOCALIZATION -#include -#endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif -_LIBCPP_BEGIN_NAMESPACE_STD - -#if _LIBCPP_STD_VER > 17 - -// TODO FMT Move the implementation in this file to its own granular headers. - -// 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; -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -using wformat_args = basic_format_args; -#endif - -template -_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) { - return _VSTD::__format_arg_store<_Context, _Args...>(__args...); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -_LIBCPP_HIDE_FROM_ABI __format_arg_store make_wformat_args(_Args&&... __args) { - return _VSTD::__format_arg_store(__args...); -} -#endif - -namespace __format { - -/// 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 _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 - _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 -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 -_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. - 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_)); -} - -template -_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"); -} - -template -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__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); - - bool __parse = *__r.__ptr == _CharT(':'); - 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 '}'"); - } - - 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 - __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type); - } else - _VSTD::visit_format_arg( - [&](auto __arg) { - if constexpr (same_as) - __throw_format_error("Argument index out of bounds"); - else if constexpr (same_as::handle>) - __arg.format(__parse_ctx, __ctx); - else { - formatter __formatter; - if (__parse) - __parse_ctx.advance_to(__formatter.parse(__parse_ctx)); - __ctx.advance_to(__formatter.format(__arg, __ctx)); - } - }, - __ctx.arg(__r.__value)); - - __begin = __parse_ctx.begin(); - if (__begin == __end || *__begin != _CharT('}')) - __throw_format_error("The replacement field misses a terminating '}'"); - - return ++__begin; -} - -template -_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator -__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) { - using _CharT = typename _ParseCtx::char_type; - static_assert(same_as); - - 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 - -template -struct _LIBCPP_TEMPLATE_VIS basic_format_string { - template - requires convertible_to> - 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)}); - } - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept { - return __str_; - } - -private: - basic_string_view<_CharT> __str_; - - 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 - 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 -using format_string = basic_format_string...>; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -using wformat_string = basic_format_string...>; -#endif - -template -requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt - __vformat_to( - _OutIt __out_it, basic_string_view<_CharT> __fmt, - basic_format_args> __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 { - __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; - _VSTD::__format::__vformat_to( - basic_format_parse_context{__fmt, __args.__size()}, - _VSTD::__format_context_create(__buffer.__make_output_iterator(), - __args)); - return _VSTD::move(__buffer).__out_it(); - } -} - -// 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. -template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) { - return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) { - return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args); -} -#endif - -template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), - _VSTD::make_format_args(__args...)); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(), - _VSTD::make_wformat_args(__args...)); -} -#endif - -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string -vformat(string_view __fmt, format_args __args) { - string __res; - _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); - return __res; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -vformat(wstring_view __fmt, wformat_args __args) { - wstring __res; - _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args); - return __res; -} -#endif - -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt, - _Args&&... __args) { - return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...)); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...)); -} -#endif - -template -_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(); -} - -template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...)); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template _OutIt, class... _Args> -_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<_Args...> __fmt, - _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...)); -} -#endif - -template -_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(); -} - -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); -} -#endif - -#ifndef _LIBCPP_HAS_NO_LOCALIZATION - -template -requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt - __vformat_to( - _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt, - basic_format_args> __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 { - __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)}; - _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).__out_it(); - } -} - -template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( - _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) { - return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, - __args); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template _OutIt> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to( - _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) { - return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt, - __args); -} -#endif - -template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), - _VSTD::make_format_args(__args...)); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt -format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(), - _VSTD::make_wformat_args(__args...)); -} -#endif - -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string -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; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -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; -} -#endif - -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc, - format_string<_Args...> __fmt, - _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), - _VSTD::make_format_args(__args...)); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring -format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(), - _VSTD::make_wformat_args(__args...)); -} -#endif - -template -_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(); -} - -template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, - _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), - _VSTD::make_format_args(__args...)); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template _OutIt, class... _Args> -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt> -format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, - _Args&&... __args) { - return _VSTD::__vformat_to_n(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(), - _VSTD::make_wformat_args(__args...)); -} -#endif - -template -_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(); -} - -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)}); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template -_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t -formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) { - return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)}); -} -#endif - -#endif // _LIBCPP_HAS_NO_LOCALIZATION - -#endif //_LIBCPP_STD_VER > 17 - -_LIBCPP_END_NAMESPACE_STD - #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT) #endif // _LIBCPP_FORMAT diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -661,10 +661,14 @@ export locale } module format_error { private header "__format/format_error.h" } + module format_functions { private header "__format/format_functions.h" } module format_fwd { private header "__format/format_fwd.h" } module format_parse_context { private header "__format/format_parse_context.h" } module format_string { private header "__format/format_string.h" } - module format_to_n_result { private header "__format/format_to_n_result.h" } + module format_to_n_result { + private header "__format/format_to_n_result.h" + export iterator.__iterator.incrementable_traits + } module formatter { private header "__format/formatter.h" } module formatter_bool { private header "__format/formatter_bool.h" } module formatter_char { private header "__format/formatter_char.h" } diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -326,6 +326,7 @@ #include <__format/format_args.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_args.h'}} #include <__format/format_context.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_context.h'}} #include <__format/format_error.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_error.h'}} +#include <__format/format_functions.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_functions.h'}} #include <__format/format_fwd.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_fwd.h'}} #include <__format/format_parse_context.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_parse_context.h'}} #include <__format/format_string.h> // expected-error@*:* {{use of private header from outside its module: '__format/format_string.h'}}