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