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