1d184958bSMark de Wever // -*- C++ -*- 2d184958bSMark de Wever //===----------------------------------------------------------------------===// 3d184958bSMark de Wever // 4d184958bSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5d184958bSMark de Wever // See https://llvm.org/LICENSE.txt for license information. 6d184958bSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7d184958bSMark de Wever // 8d184958bSMark de Wever //===----------------------------------------------------------------------===// 9d184958bSMark de Wever 10d184958bSMark de Wever #ifndef _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H 11d184958bSMark de Wever #define _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H 12d184958bSMark de Wever 13d184958bSMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 14d184958bSMark de Wever # pragma GCC system_header 15d184958bSMark de Wever #endif 16d184958bSMark de Wever 17ed8ea2bbSMark de Wever #include <__algorithm/ranges_copy.h> 18af5fc4b4SMark de Wever #include <__chrono/statically_widen.h> 19d184958bSMark de Wever #include <__concepts/same_as.h> 20d184958bSMark de Wever #include <__config> 21d184958bSMark de Wever #include <__format/concepts.h> 22d184958bSMark de Wever #include <__format/formatter.h> 2322e8525dSMark de Wever #include <__format/range_formatter.h> 24ed8ea2bbSMark de Wever #include <__iterator/back_insert_iterator.h> 25d184958bSMark de Wever #include <__ranges/concepts.h> 26ed8ea2bbSMark de Wever #include <__ranges/data.h> 277b580d8bSMark de Wever #include <__ranges/from_range.h> 28ed8ea2bbSMark de Wever #include <__ranges/size.h> 29285e1e2aSMark de Wever #include <__type_traits/conditional.h> 30d184958bSMark de Wever #include <__type_traits/remove_cvref.h> 31d184958bSMark de Wever #include <__utility/pair.h> 3222e8525dSMark de Wever #include <string_view> 33d184958bSMark de Wever 34d184958bSMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD 35d184958bSMark de Wever 364f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 23 37d184958bSMark de Wever 38d184958bSMark de Wever template <class _Rp, class _CharT> 39d184958bSMark de Wever concept __const_formattable_range = 40d184958bSMark de Wever ranges::input_range<const _Rp> && formattable<ranges::range_reference_t<const _Rp>, _CharT>; 41d184958bSMark de Wever 42d184958bSMark de Wever template <class _Rp, class _CharT> 43*f6958523SNikolas Klauser using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; 44d184958bSMark de Wever 45d184958bSMark de Wever _LIBCPP_DIAGNOSTIC_PUSH 46d184958bSMark de Wever _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") 47d184958bSMark de Wever _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") 48d184958bSMark de Wever // This shadows map, set, and string. 49d184958bSMark de Wever enum class range_format { disabled, map, set, sequence, string, debug_string }; 50d184958bSMark de Wever _LIBCPP_DIAGNOSTIC_POP 51d184958bSMark de Wever 52d184958bSMark de Wever // There is no definition of this struct, it's purely intended to be used to 53d184958bSMark de Wever // generate diagnostics. 54d184958bSMark de Wever template <class _Rp> 55d184958bSMark de Wever struct _LIBCPP_TEMPLATE_VIS __instantiated_the_primary_template_of_format_kind; 56d184958bSMark de Wever 57d184958bSMark de Wever template <class _Rp> 58d184958bSMark de Wever constexpr range_format format_kind = [] { 59d184958bSMark de Wever // [format.range.fmtkind]/1 60d184958bSMark de Wever // A program that instantiates the primary template of format_kind is ill-formed. 61d184958bSMark de Wever static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); 62d184958bSMark de Wever return range_format::disabled; 63d184958bSMark de Wever }(); 64d184958bSMark de Wever 65d184958bSMark de Wever template <ranges::input_range _Rp> 66d184958bSMark de Wever requires same_as<_Rp, remove_cvref_t<_Rp>> 67d184958bSMark de Wever inline constexpr range_format format_kind<_Rp> = [] { 68d184958bSMark de Wever // [format.range.fmtkind]/2 69d184958bSMark de Wever 70d184958bSMark de Wever // 2.1 If same_as<remove_cvref_t<ranges::range_reference_t<R>>, R> is true, 71d184958bSMark de Wever // Otherwise format_kind<R> is range_format::disabled. 72d184958bSMark de Wever if constexpr (same_as<remove_cvref_t<ranges::range_reference_t<_Rp>>, _Rp>) 73d184958bSMark de Wever return range_format::disabled; 74d184958bSMark de Wever // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: 75d184958bSMark de Wever else if constexpr (requires { typename _Rp::key_type; }) { 76d184958bSMark de Wever // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... 77d184958bSMark de Wever if constexpr (requires { typename _Rp::mapped_type; } && 78d184958bSMark de Wever // 2.2.1 ... If either U is a specialization of pair or U is a specialization 79d184958bSMark de Wever // of tuple and tuple_size_v<U> == 2 80d184958bSMark de Wever __fmt_pair_like<remove_cvref_t<ranges::range_reference_t<_Rp>>>) 81d184958bSMark de Wever return range_format::map; 82d184958bSMark de Wever else 83d184958bSMark de Wever // 2.2.2 Otherwise format_kind<R> is range_format::set. 84d184958bSMark de Wever return range_format::set; 85d184958bSMark de Wever } else 86d184958bSMark de Wever // 2.3 Otherwise, format_kind<R> is range_format::sequence. 87d184958bSMark de Wever return range_format::sequence; 88d184958bSMark de Wever }(); 89d184958bSMark de Wever 90d184958bSMark de Wever template <range_format _Kp, ranges::input_range _Rp, class _CharT> 913d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter; 92d184958bSMark de Wever 93d184958bSMark de Wever // Required specializations 94d184958bSMark de Wever 95d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT> 963d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::sequence, _Rp, _CharT> { 9722e8525dSMark de Wever private: 98*f6958523SNikolas Klauser using __maybe_const_r _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; 9922e8525dSMark de Wever range_formatter<remove_cvref_t<ranges::range_reference_t<__maybe_const_r>>, _CharT> __underlying_; 10022e8525dSMark de Wever 10122e8525dSMark de Wever public: 102f68a536aSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { 10322e8525dSMark de Wever __underlying_.set_separator(__separator); 10422e8525dSMark de Wever } 10522e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void 106f68a536aSMark de Wever set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { 10722e8525dSMark de Wever __underlying_.set_brackets(__opening_bracket, __closing_bracket); 10822e8525dSMark de Wever } 10922e8525dSMark de Wever 11022e8525dSMark de Wever template <class _ParseContext> 11122e8525dSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { 11222e8525dSMark de Wever return __underlying_.parse(__ctx); 11322e8525dSMark de Wever } 11422e8525dSMark de Wever 1151e24b4d3SNikolas Klauser template <class _FormatContext> 1161e24b4d3SNikolas Klauser _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator 1171e24b4d3SNikolas Klauser format(__maybe_const_r& __range, _FormatContext& __ctx) const { 11822e8525dSMark de Wever return __underlying_.format(__range, __ctx); 11922e8525dSMark de Wever } 120d184958bSMark de Wever }; 121d184958bSMark de Wever 122d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT> 1233d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::map, _Rp, _CharT> { 124af5fc4b4SMark de Wever private: 125*f6958523SNikolas Klauser using __maybe_const_map _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; 126*f6958523SNikolas Klauser using __element_type _LIBCPP_NODEBUG = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>; 127af5fc4b4SMark de Wever range_formatter<__element_type, _CharT> __underlying_; 128af5fc4b4SMark de Wever 129af5fc4b4SMark de Wever public: 130af5fc4b4SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() 131af5fc4b4SMark de Wever requires(__fmt_pair_like<__element_type>) 132af5fc4b4SMark de Wever { 133af5fc4b4SMark de Wever __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); 134af5fc4b4SMark de Wever __underlying_.underlying().set_brackets({}, {}); 135af5fc4b4SMark de Wever __underlying_.underlying().set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); 136af5fc4b4SMark de Wever } 137af5fc4b4SMark de Wever 138af5fc4b4SMark de Wever template <class _ParseContext> 139af5fc4b4SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { 140af5fc4b4SMark de Wever return __underlying_.parse(__ctx); 141af5fc4b4SMark de Wever } 142af5fc4b4SMark de Wever 143af5fc4b4SMark de Wever template <class _FormatContext> 144af5fc4b4SMark de Wever _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator 145af5fc4b4SMark de Wever format(__maybe_const_map& __range, _FormatContext& __ctx) const { 146af5fc4b4SMark de Wever return __underlying_.format(__range, __ctx); 147af5fc4b4SMark de Wever } 148d184958bSMark de Wever }; 149d184958bSMark de Wever 150d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT> 1513d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::set, _Rp, _CharT> { 152857cbb92SMark de Wever private: 153*f6958523SNikolas Klauser using __maybe_const_set _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; 154*f6958523SNikolas Klauser using __element_type _LIBCPP_NODEBUG = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>; 155857cbb92SMark de Wever range_formatter<__element_type, _CharT> __underlying_; 156857cbb92SMark de Wever 157857cbb92SMark de Wever public: 158857cbb92SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() { 159857cbb92SMark de Wever __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); 160857cbb92SMark de Wever } 161857cbb92SMark de Wever 162857cbb92SMark de Wever template <class _ParseContext> 163857cbb92SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { 164857cbb92SMark de Wever return __underlying_.parse(__ctx); 165857cbb92SMark de Wever } 166857cbb92SMark de Wever 167857cbb92SMark de Wever template <class _FormatContext> 168857cbb92SMark de Wever _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator 169857cbb92SMark de Wever format(__maybe_const_set& __range, _FormatContext& __ctx) const { 170857cbb92SMark de Wever return __underlying_.format(__range, __ctx); 171857cbb92SMark de Wever } 172d184958bSMark de Wever }; 173d184958bSMark de Wever 174d184958bSMark de Wever template <range_format _Kp, ranges::input_range _Rp, class _CharT> 175d184958bSMark de Wever requires(_Kp == range_format::string || _Kp == range_format::debug_string) 1763d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<_Kp, _Rp, _CharT> { 177ed8ea2bbSMark de Wever private: 178ed8ea2bbSMark de Wever // This deviates from the Standard, there the exposition only type is 179ed8ea2bbSMark de Wever // formatter<basic_string<charT>, charT> underlying_; 180ed8ea2bbSMark de Wever // Using a string_view allows the format function to avoid a copy of the 181ed8ea2bbSMark de Wever // input range when it is a contigious range. 182ed8ea2bbSMark de Wever formatter<basic_string_view<_CharT>, _CharT> __underlying_; 183ed8ea2bbSMark de Wever 184ed8ea2bbSMark de Wever public: 185ed8ea2bbSMark de Wever template <class _ParseContext> 186ed8ea2bbSMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { 187ed8ea2bbSMark de Wever typename _ParseContext::iterator __i = __underlying_.parse(__ctx); 188ed8ea2bbSMark de Wever if constexpr (_Kp == range_format::debug_string) 189ed8ea2bbSMark de Wever __underlying_.set_debug_format(); 190ed8ea2bbSMark de Wever return __i; 191ed8ea2bbSMark de Wever } 192ed8ea2bbSMark de Wever 193ed8ea2bbSMark de Wever template <class _FormatContext> 194ed8ea2bbSMark de Wever _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator 195ed8ea2bbSMark de Wever format(conditional_t<ranges::input_range<const _Rp>, const _Rp&, _Rp&> __range, _FormatContext& __ctx) const { 196ed8ea2bbSMark de Wever // When the range is contiguous use a basic_string_view instead to avoid a 197ed8ea2bbSMark de Wever // copy of the underlying data. The basic_string_view formatter 198ed8ea2bbSMark de Wever // specialization is the "basic" string formatter in libc++. 199ed8ea2bbSMark de Wever if constexpr (ranges::contiguous_range<_Rp> && std::ranges::sized_range<_Rp>) 200ed8ea2bbSMark de Wever return __underlying_.format(basic_string_view<_CharT>{ranges::data(__range), ranges::size(__range)}, __ctx); 2017b580d8bSMark de Wever else 2027b580d8bSMark de Wever return __underlying_.format(basic_string<_CharT>{from_range, __range}, __ctx); 203ed8ea2bbSMark de Wever } 204d184958bSMark de Wever }; 205d184958bSMark de Wever 206d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT> 207d184958bSMark de Wever requires(format_kind<_Rp> != range_format::disabled && formattable<ranges::range_reference_t<_Rp>, _CharT>) 2083d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS formatter<_Rp, _CharT> : __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {}; 209d184958bSMark de Wever 2104f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 23 211d184958bSMark de Wever 212d184958bSMark de Wever _LIBCPP_END_NAMESPACE_STD 213d184958bSMark de Wever 214d184958bSMark de Wever #endif // _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H 215