File indexing completed on 2026-05-03 08:13:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___CXX03___FORMAT_FORMATTER_OUTPUT_H
0011 #define _LIBCPP___CXX03___FORMAT_FORMATTER_OUTPUT_H
0012
0013 #include <__cxx03/__algorithm/ranges_copy.h>
0014 #include <__cxx03/__algorithm/ranges_fill_n.h>
0015 #include <__cxx03/__algorithm/ranges_transform.h>
0016 #include <__cxx03/__bit/countl.h>
0017 #include <__cxx03/__concepts/same_as.h>
0018 #include <__cxx03/__config>
0019 #include <__cxx03/__format/buffer.h>
0020 #include <__cxx03/__format/concepts.h>
0021 #include <__cxx03/__format/formatter.h>
0022 #include <__cxx03/__format/parser_std_format_spec.h>
0023 #include <__cxx03/__format/unicode.h>
0024 #include <__cxx03/__iterator/back_insert_iterator.h>
0025 #include <__cxx03/__iterator/concepts.h>
0026 #include <__cxx03/__iterator/iterator_traits.h>
0027 #include <__cxx03/__memory/addressof.h>
0028 #include <__cxx03/__memory/pointer_traits.h>
0029 #include <__cxx03/__utility/move.h>
0030 #include <__cxx03/__utility/unreachable.h>
0031 #include <__cxx03/cstddef>
0032 #include <__cxx03/string_view>
0033
0034 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0035 # pragma GCC system_header
0036 #endif
0037
0038 _LIBCPP_PUSH_MACROS
0039 #include <__cxx03/__undef_macros>
0040
0041 _LIBCPP_BEGIN_NAMESPACE_STD
0042
0043 #if _LIBCPP_STD_VER >= 20
0044
0045 namespace __formatter {
0046
0047 _LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char __c) {
0048 switch (__c) {
0049 case 'a':
0050 return 'A';
0051 case 'b':
0052 return 'B';
0053 case 'c':
0054 return 'C';
0055 case 'd':
0056 return 'D';
0057 case 'e':
0058 return 'E';
0059 case 'f':
0060 return 'F';
0061 }
0062 return __c;
0063 }
0064
0065 struct _LIBCPP_EXPORTED_FROM_ABI __padding_size_result {
0066 size_t __before_;
0067 size_t __after_;
0068 };
0069
0070 _LIBCPP_HIDE_FROM_ABI constexpr __padding_size_result
0071 __padding_size(size_t __size, size_t __width, __format_spec::__alignment __align) {
0072 _LIBCPP_ASSERT_INTERNAL(__width > __size, "don't call this function when no padding is required");
0073 _LIBCPP_ASSERT_INTERNAL(
0074 __align != __format_spec::__alignment::__zero_padding, "the caller should have handled the zero-padding");
0075
0076 size_t __fill = __width - __size;
0077 switch (__align) {
0078 case __format_spec::__alignment::__zero_padding:
0079 __libcpp_unreachable();
0080
0081 case __format_spec::__alignment::__left:
0082 return {0, __fill};
0083
0084 case __format_spec::__alignment::__center: {
0085
0086
0087
0088 size_t __before = __fill / 2;
0089 size_t __after = __fill - __before;
0090 return {__before, __after};
0091 }
0092 case __format_spec::__alignment::__default:
0093 case __format_spec::__alignment::__right:
0094 return {__fill, 0};
0095 }
0096 __libcpp_unreachable();
0097 }
0098
0099
0100
0101
0102 template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT>
0103 _LIBCPP_HIDE_FROM_ABI auto
0104 __copy(basic_string_view<_CharT> __str, output_iterator<const _OutCharT&> auto __out_it) -> decltype(__out_it) {
0105 if constexpr (std::same_as<decltype(__out_it), std::back_insert_iterator<__format::__output_buffer<_OutCharT>>>) {
0106 __out_it.__get_container()->__copy(__str);
0107 return __out_it;
0108 } else if constexpr (std::same_as<decltype(__out_it), typename __format::__retarget_buffer<_OutCharT>::__iterator>) {
0109 __out_it.__buffer_->__copy(__str);
0110 return __out_it;
0111 } else {
0112 return std::ranges::copy(__str, std::move(__out_it)).out;
0113 }
0114 }
0115
0116 template <contiguous_iterator _Iterator,
0117 __fmt_char_type _CharT = typename iterator_traits<_Iterator>::value_type,
0118 __fmt_char_type _OutCharT = _CharT>
0119 _LIBCPP_HIDE_FROM_ABI auto
0120 __copy(_Iterator __first, _Iterator __last, output_iterator<const _OutCharT&> auto __out_it) -> decltype(__out_it) {
0121 return __formatter::__copy(basic_string_view{__first, __last}, std::move(__out_it));
0122 }
0123
0124 template <contiguous_iterator _Iterator,
0125 __fmt_char_type _CharT = typename iterator_traits<_Iterator>::value_type,
0126 __fmt_char_type _OutCharT = _CharT>
0127 _LIBCPP_HIDE_FROM_ABI auto
0128 __copy(_Iterator __first, size_t __n, output_iterator<const _OutCharT&> auto __out_it) -> decltype(__out_it) {
0129 return __formatter::__copy(basic_string_view{std::to_address(__first), __n}, std::move(__out_it));
0130 }
0131
0132
0133
0134
0135 template <contiguous_iterator _Iterator,
0136 __fmt_char_type _CharT = typename iterator_traits<_Iterator>::value_type,
0137 __fmt_char_type _OutCharT = _CharT,
0138 class _UnaryOperation>
0139 _LIBCPP_HIDE_FROM_ABI auto
0140 __transform(_Iterator __first,
0141 _Iterator __last,
0142 output_iterator<const _OutCharT&> auto __out_it,
0143 _UnaryOperation __operation) -> decltype(__out_it) {
0144 if constexpr (std::same_as<decltype(__out_it), std::back_insert_iterator<__format::__output_buffer<_OutCharT>>>) {
0145 __out_it.__get_container()->__transform(__first, __last, std::move(__operation));
0146 return __out_it;
0147 } else if constexpr (std::same_as<decltype(__out_it), typename __format::__retarget_buffer<_OutCharT>::__iterator>) {
0148 __out_it.__buffer_->__transform(__first, __last, std::move(__operation));
0149 return __out_it;
0150 } else {
0151 return std::ranges::transform(__first, __last, std::move(__out_it), __operation).out;
0152 }
0153 }
0154
0155
0156
0157
0158 template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt>
0159 _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, _CharT __value) {
0160 if constexpr (std::same_as<decltype(__out_it), std::back_insert_iterator<__format::__output_buffer<_CharT>>>) {
0161 __out_it.__get_container()->__fill(__n, __value);
0162 return __out_it;
0163 } else if constexpr (std::same_as<decltype(__out_it), typename __format::__retarget_buffer<_CharT>::__iterator>) {
0164 __out_it.__buffer_->__fill(__n, __value);
0165 return __out_it;
0166 } else {
0167 return std::ranges::fill_n(std::move(__out_it), __n, __value);
0168 }
0169 }
0170
0171 # ifndef _LIBCPP_HAS_NO_UNICODE
0172 template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt>
0173 requires(same_as<_CharT, char>)
0174 _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) {
0175 std::size_t __bytes = std::countl_one(static_cast<unsigned char>(__value.__data[0]));
0176 if (__bytes == 0)
0177 return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]);
0178
0179 for (size_t __i = 0; __i < __n; ++__i)
0180 __out_it = __formatter::__copy(
0181 std::addressof(__value.__data[0]), std::addressof(__value.__data[0]) + __bytes, std::move(__out_it));
0182 return __out_it;
0183 }
0184
0185 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
0186 template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt>
0187 requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2)
0188 _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) {
0189 if (!__unicode::__is_high_surrogate(__value.__data[0]))
0190 return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]);
0191
0192 for (size_t __i = 0; __i < __n; ++__i)
0193 __out_it = __formatter::__copy(
0194 std::addressof(__value.__data[0]), std::addressof(__value.__data[0]) + 2, std::move(__out_it));
0195 return __out_it;
0196 }
0197
0198 template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt>
0199 requires(same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4)
0200 _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) {
0201 return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]);
0202 }
0203 # endif
0204 # else
0205 template <__fmt_char_type _CharT, output_iterator<const _CharT&> _OutIt>
0206 _LIBCPP_HIDE_FROM_ABI _OutIt __fill(_OutIt __out_it, size_t __n, __format_spec::__code_point<_CharT> __value) {
0207 return __formatter::__fill(std::move(__out_it), __n, __value.__data[0]);
0208 }
0209 # endif
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 template <class _CharT, class _ParserCharT>
0233 _LIBCPP_HIDE_FROM_ABI auto
0234 __write(basic_string_view<_CharT> __str,
0235 output_iterator<const _CharT&> auto __out_it,
0236 __format_spec::__parsed_specifications<_ParserCharT> __specs,
0237 ptrdiff_t __size) -> decltype(__out_it) {
0238 if (__size >= __specs.__width_)
0239 return __formatter::__copy(__str, std::move(__out_it));
0240
0241 __padding_size_result __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__std_.__alignment_);
0242 __out_it = __formatter::__fill(std::move(__out_it), __padding.__before_, __specs.__fill_);
0243 __out_it = __formatter::__copy(__str, std::move(__out_it));
0244 return __formatter::__fill(std::move(__out_it), __padding.__after_, __specs.__fill_);
0245 }
0246
0247 template <contiguous_iterator _Iterator, class _ParserCharT>
0248 _LIBCPP_HIDE_FROM_ABI auto
0249 __write(_Iterator __first,
0250 _Iterator __last,
0251 output_iterator<const iter_value_t<_Iterator>&> auto __out_it,
0252 __format_spec::__parsed_specifications<_ParserCharT> __specs,
0253 ptrdiff_t __size) -> decltype(__out_it) {
0254 _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "Not a valid range");
0255 return __formatter::__write(basic_string_view{__first, __last}, std::move(__out_it), __specs, __size);
0256 }
0257
0258
0259
0260
0261 template <contiguous_iterator _Iterator, class _ParserCharT>
0262 _LIBCPP_HIDE_FROM_ABI auto
0263 __write(_Iterator __first,
0264 _Iterator __last,
0265 output_iterator<const iter_value_t<_Iterator>&> auto __out_it,
0266 __format_spec::__parsed_specifications<_ParserCharT> __specs) -> decltype(__out_it) {
0267 _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "Not a valid range");
0268 return __formatter::__write(__first, __last, std::move(__out_it), __specs, __last - __first);
0269 }
0270
0271 template <contiguous_iterator _Iterator,
0272 class _CharT = typename iterator_traits<_Iterator>::value_type,
0273 class _ParserCharT,
0274 class _UnaryOperation>
0275 _LIBCPP_HIDE_FROM_ABI auto __write_transformed(
0276 _Iterator __first,
0277 _Iterator __last,
0278 output_iterator<const _CharT&> auto __out_it,
0279 __format_spec::__parsed_specifications<_ParserCharT> __specs,
0280 _UnaryOperation __op) -> decltype(__out_it) {
0281 _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "Not a valid range");
0282
0283 ptrdiff_t __size = __last - __first;
0284 if (__size >= __specs.__width_)
0285 return __formatter::__transform(__first, __last, std::move(__out_it), __op);
0286
0287 __padding_size_result __padding = __formatter::__padding_size(__size, __specs.__width_, __specs.__alignment_);
0288 __out_it = __formatter::__fill(std::move(__out_it), __padding.__before_, __specs.__fill_);
0289 __out_it = __formatter::__transform(__first, __last, std::move(__out_it), __op);
0290 return __formatter::__fill(std::move(__out_it), __padding.__after_, __specs.__fill_);
0291 }
0292
0293
0294
0295
0296
0297
0298
0299 template <class _CharT>
0300 _LIBCPP_HIDE_FROM_ABI auto __write_string_no_precision(
0301 basic_string_view<_CharT> __str,
0302 output_iterator<const _CharT&> auto __out_it,
0303 __format_spec::__parsed_specifications<_CharT> __specs) -> decltype(__out_it) {
0304 _LIBCPP_ASSERT_INTERNAL(!__specs.__has_precision(), "use __write_string");
0305
0306
0307 if (!__specs.__has_width())
0308 return __formatter::__copy(__str, std::move(__out_it));
0309
0310
0311
0312
0313 size_t __size =
0314 __format_spec::__estimate_column_width(__str, __specs.__width_, __format_spec::__column_width_rounding::__up)
0315 .__width_;
0316 return __formatter::__write(__str, std::move(__out_it), __specs, __size);
0317 }
0318
0319 template <class _CharT>
0320 _LIBCPP_HIDE_FROM_ABI int __truncate(basic_string_view<_CharT>& __str, int __precision) {
0321 __format_spec::__column_width_result __result =
0322 __format_spec::__estimate_column_width(__str, __precision, __format_spec::__column_width_rounding::__down);
0323 __str = basic_string_view<_CharT>{__str.begin(), __result.__last_};
0324 return __result.__width_;
0325 }
0326
0327 }
0328
0329 #endif
0330
0331 _LIBCPP_END_NAMESPACE_STD
0332
0333 _LIBCPP_POP_MACROS
0334
0335 #endif