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_H 11 #define _LIBCPP___FORMAT_FORMATTER_H 12 13 #include <__algorithm/copy.h> 14 #include <__algorithm/fill_n.h> 15 #include <__availability> 16 #include <__config> 17 #include <__format/format_error.h> 18 #include <__format/format_fwd.h> 19 #include <__format/format_string.h> 20 #include <__format/parser_std_format_spec.h> 21 #include <concepts> 22 #include <string_view> 23 24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 25 #pragma GCC system_header 26 #endif 27 28 _LIBCPP_PUSH_MACROS 29 #include <__undef_macros> 30 31 _LIBCPP_BEGIN_NAMESPACE_STD 32 33 #if _LIBCPP_STD_VER > 17 34 35 // TODO FMT Remove this once we require compilers with proper C++20 support. 36 // If the compiler has no concepts support, the format header will be disabled. 37 // Without concepts support enable_if needs to be used and that too much effort 38 // to support compilers with partial C++20 support. 39 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) 40 41 // Currently not implemented specializations throw an exception when used. This 42 // does not conform to the Standard. However not all Standard defined formatters 43 // have been implemented yet. Until that time the current behavior is intended. 44 // TODO FMT Disable the default template. 45 template <class _Tp, class _CharT> 46 struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter { 47 _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI auto parse(auto& __parse_ctx) 48 -> decltype(__parse_ctx.begin()) { 49 __throw(); 50 } 51 52 _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI auto format(_Tp, auto& __ctx) 53 -> decltype(__ctx.out()) { 54 __throw(); 55 } 56 57 private: 58 _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw() { 59 __throw_format_error("Argument type not implemented yet"); 60 } 61 }; 62 63 namespace __format_spec { 64 65 _LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, 66 _Flags::_Sign __sign) { 67 if (__negative) 68 *__buf++ = '-'; 69 else 70 switch (__sign) { 71 case _Flags::_Sign::__default: 72 case _Flags::_Sign::__minus: 73 // No sign added. 74 break; 75 case _Flags::_Sign::__plus: 76 *__buf++ = '+'; 77 break; 78 case _Flags::_Sign::__space: 79 *__buf++ = ' '; 80 break; 81 } 82 83 return __buf; 84 } 85 86 _LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char c) { 87 switch (c) { 88 case 'a': 89 return 'A'; 90 case 'b': 91 return 'B'; 92 case 'c': 93 return 'C'; 94 case 'd': 95 return 'D'; 96 case 'e': 97 return 'E'; 98 case 'f': 99 return 'F'; 100 } 101 return c; 102 } 103 104 } // namespace __format_spec 105 106 namespace __formatter { 107 108 /** The character types that formatters are specialized for. */ 109 template <class _CharT> 110 concept __char_type = same_as<_CharT, char> || same_as<_CharT, wchar_t>; 111 112 struct _LIBCPP_TEMPLATE_VIS __padding_size_result { 113 size_t __before; 114 size_t __after; 115 }; 116 117 _LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result 118 __padding_size(size_t __size, size_t __width, 119 __format_spec::_Flags::_Alignment __align) { 120 _LIBCPP_ASSERT(__width > __size, 121 "Don't call this function when no padding is required"); 122 _LIBCPP_ASSERT( 123 __align != __format_spec::_Flags::_Alignment::__default, 124 "Caller should adjust the default to the value required by the type"); 125 126 size_t __fill = __width - __size; 127 switch (__align) { 128 case __format_spec::_Flags::_Alignment::__default: 129 _LIBCPP_UNREACHABLE(); 130 131 case __format_spec::_Flags::_Alignment::__left: 132 return {0, __fill}; 133 134 case __format_spec::_Flags::_Alignment::__center: { 135 // The extra padding is divided per [format.string.std]/3 136 // __before = floor(__fill, 2); 137 // __after = ceil(__fill, 2); 138 size_t __before = __fill / 2; 139 size_t __after = __fill - __before; 140 return {__before, __after}; 141 } 142 case __format_spec::_Flags::_Alignment::__right: 143 return {__fill, 0}; 144 } 145 _LIBCPP_UNREACHABLE(); 146 } 147 148 /** 149 * Writes the input to the output with the required padding. 150 * 151 * Since the output column width is specified the function can be used for 152 * ASCII and Unicode input. 153 * 154 * @pre [@a __first, @a __last) is a valid range. 155 * @pre @a __size <= @a __width. Using this function when this pre-condition 156 * doesn't hold incurs an unwanted overhead. 157 * 158 * @param __out_it The output iterator to write to. 159 * @param __first Pointer to the first element to write. 160 * @param __last Pointer beyond the last element to write. 161 * @param __size The (estimated) output column width. When the elements 162 * to be written are ASCII the following condition holds 163 * @a __size == @a __last - @a __first. 164 * @param __width The number of output columns to write. 165 * @param __fill The character used for the alignment of the output. 166 * TODO FMT Will probably change to support Unicode grapheme 167 * cluster. 168 * @param __alignment The requested alignment. 169 * 170 * @returns An iterator pointing beyond the last element written. 171 * 172 * @note The type of the elements in range [@a __first, @a __last) can differ 173 * from the type of @a __fill. Integer output uses @c std::to_chars for its 174 * conversion, which means the [@a __first, @a __last) always contains elements 175 * of the type @c char. 176 */ 177 template <class _CharT, class _Fill> 178 _LIBCPP_HIDE_FROM_ABI auto 179 __write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first, 180 const _CharT* __last, size_t __size, size_t __width, _Fill __fill, 181 __format_spec::_Flags::_Alignment __alignment) -> decltype(__out_it) { 182 183 _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); 184 _LIBCPP_ASSERT(__size < __width, "Precondition failure"); 185 186 __padding_size_result __padding = 187 __padding_size(__size, __width, __alignment); 188 __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill); 189 __out_it = _VSTD::copy(__first, __last, _VSTD::move(__out_it)); 190 return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill); 191 } 192 193 /** 194 * @overload 195 * 196 * Uses a transformation operation before writing an element. 197 * 198 * TODO FMT Fill will probably change to support Unicode grapheme cluster. 199 */ 200 template <class _CharT, class _UnaryOperation, class _Fill> 201 _LIBCPP_HIDE_FROM_ABI auto 202 __write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first, 203 const _CharT* __last, size_t __size, _UnaryOperation __op, 204 size_t __width, _Fill __fill, 205 __format_spec::_Flags::_Alignment __alignment) -> decltype(__out_it) { 206 207 _LIBCPP_ASSERT(__first <= __last, "Not a valid range"); 208 _LIBCPP_ASSERT(__size < __width, "Precondition failure"); 209 210 __padding_size_result __padding = 211 __padding_size(__size, __width, __alignment); 212 __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill); 213 __out_it = _VSTD::transform(__first, __last, _VSTD::move(__out_it), __op); 214 return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill); 215 } 216 217 /** 218 * Writes Unicode input to the output with the required padding. 219 * 220 * This function does almost the same as the @ref __write function, but handles 221 * the width estimation of the Unicode input. 222 * 223 * @param __str The range [@a __first, @a __last). 224 * @param __precision The width to truncate the input string to, use @c -1 for 225 * no limit. 226 */ 227 template <class _CharT, class _Fill> 228 _LIBCPP_HIDE_FROM_ABI auto 229 __write_unicode(output_iterator<const _CharT&> auto __out_it, 230 basic_string_view<_CharT> __str, ptrdiff_t __width, 231 ptrdiff_t __precision, _Fill __fill, 232 __format_spec::_Flags::_Alignment __alignment) 233 -> decltype(__out_it) { 234 235 // This value changes when there Unicode column width limits the output 236 // size. 237 auto __last = __str.end(); 238 if (__width != 0 || __precision != -1) { 239 __format_spec::__string_alignment<_CharT> __format_traits = 240 __format_spec::__get_string_alignment(__str.begin(), __str.end(), 241 __width, __precision); 242 243 if (__format_traits.__align) 244 return __write(_VSTD::move(__out_it), __str.begin(), 245 __format_traits.__last, __format_traits.__size, __width, 246 __fill, __alignment); 247 248 // No alignment required update the output based on the precision. 249 // This might be the same as __str.end(). 250 __last = __format_traits.__last; 251 } 252 253 // Copy the input to the output. The output size might be limited by the 254 // precision. 255 return _VSTD::copy(__str.begin(), __last, _VSTD::move(__out_it)); 256 } 257 258 } // namespace __formatter 259 260 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 261 262 #endif //_LIBCPP_STD_VER > 17 263 264 _LIBCPP_END_NAMESPACE_STD 265 266 _LIBCPP_POP_MACROS 267 268 #endif // _LIBCPP___FORMAT_FORMATTER_H 269