1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___FORMAT_FORMATTER_STRING_H 11 #define _LIBCPP___FORMAT_FORMATTER_STRING_H 12 13 #include <__config> 14 #include <__format/concepts.h> 15 #include <__format/format_parse_context.h> 16 #include <__format/formatter.h> 17 #include <__format/formatter_output.h> 18 #include <__format/parser_std_format_spec.h> 19 #include <__format/write_escaped.h> 20 #include <string> 21 #include <string_view> 22 23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 24 # pragma GCC system_header 25 #endif 26 27 _LIBCPP_BEGIN_NAMESPACE_STD 28 29 #if _LIBCPP_STD_VER >= 20 30 31 template <__fmt_char_type _CharT> 32 struct _LIBCPP_TEMPLATE_VIS __formatter_string { 33 public: 34 template <class _ParseContext> parse__formatter_string35 _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { 36 typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_string); 37 __format_spec::__process_display_type_string(__parser_.__type_); 38 return __result; 39 } 40 41 template <class _FormatContext> 42 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format__formatter_string43 format(basic_string_view<_CharT> __str, _FormatContext& __ctx) const { 44 # if _LIBCPP_STD_VER >= 23 45 if (__parser_.__type_ == __format_spec::__type::__debug) 46 return __formatter::__format_escaped_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); 47 # endif 48 49 return __formatter::__write_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx)); 50 } 51 52 # if _LIBCPP_STD_VER >= 23 set_debug_format__formatter_string53 _LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; } 54 # endif 55 56 __format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left}; 57 }; 58 59 // Formatter const char*. 60 template <__fmt_char_type _CharT> 61 struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT*, _CharT> : public __formatter_string<_CharT> { 62 using _Base = __formatter_string<_CharT>; 63 64 template <class _FormatContext> 65 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT* __str, _FormatContext& __ctx) const { 66 _LIBCPP_ASSERT_INTERNAL(__str, "The basic_format_arg constructor should have prevented an invalid pointer."); 67 68 __format_spec::__parsed_specifications<_CharT> __specs = _Base::__parser_.__get_parsed_std_specifications(__ctx); 69 # if _LIBCPP_STD_VER >= 23 70 if (_Base::__parser_.__type_ == __format_spec::__type::__debug) 71 return __formatter::__format_escaped_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); 72 # endif 73 74 // When using a center or right alignment and the width option the length 75 // of __str must be known to add the padding upfront. This case is handled 76 // by the base class by converting the argument to a basic_string_view. 77 // 78 // When using left alignment and the width option the padding is added 79 // after outputting __str so the length can be determined while outputting 80 // __str. The same holds true for the precision, during outputting __str it 81 // can be validated whether the precision threshold has been reached. For 82 // now these optimizations aren't implemented. Instead the base class 83 // handles these options. 84 // TODO FMT Implement these improvements. 85 if (__specs.__has_width() || __specs.__has_precision()) 86 return __formatter::__write_string(basic_string_view<_CharT>{__str}, __ctx.out(), __specs); 87 88 // No formatting required, copy the string to the output. 89 auto __out_it = __ctx.out(); 90 while (*__str) 91 *__out_it++ = *__str++; 92 return __out_it; 93 } 94 }; 95 96 // Formatter char*. 97 template <__fmt_char_type _CharT> 98 struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter<const _CharT*, _CharT> { 99 using _Base = formatter<const _CharT*, _CharT>; 100 101 template <class _FormatContext> 102 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT* __str, _FormatContext& __ctx) const { 103 return _Base::format(__str, __ctx); 104 } 105 }; 106 107 // Formatter char[]. 108 template <__fmt_char_type _CharT, size_t _Size> 109 struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { 110 using _Base = __formatter_string<_CharT>; 111 112 template <class _FormatContext> 113 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator 114 format(const _CharT (&__str)[_Size], _FormatContext& __ctx) const { 115 return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx); 116 } 117 }; 118 119 // Formatter std::string. 120 template <__fmt_char_type _CharT, class _Traits, class _Allocator> 121 struct _LIBCPP_TEMPLATE_VIS formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT> 122 : public __formatter_string<_CharT> { 123 using _Base = __formatter_string<_CharT>; 124 125 template <class _FormatContext> 126 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator 127 format(const basic_string<_CharT, _Traits, _Allocator>& __str, _FormatContext& __ctx) const { 128 // Drop _Traits and _Allocator to have one std::basic_string formatter. 129 return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); 130 } 131 }; 132 133 // Formatter std::string_view. 134 template <__fmt_char_type _CharT, class _Traits> 135 struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT> : public __formatter_string<_CharT> { 136 using _Base = __formatter_string<_CharT>; 137 138 template <class _FormatContext> 139 _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator 140 format(basic_string_view<_CharT, _Traits> __str, _FormatContext& __ctx) const { 141 // Drop _Traits to have one std::basic_string_view formatter. 142 return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx); 143 } 144 }; 145 146 #endif //_LIBCPP_STD_VER >= 20 147 148 _LIBCPP_END_NAMESPACE_STD 149 150 #endif // _LIBCPP___FORMAT_FORMATTER_STRING_H 151