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