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