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_FORMAT_STRING_H
11 #define _LIBCPP___FORMAT_FORMAT_STRING_H
12
13 #include <__assert>
14 #include <__config>
15 #include <__format/format_error.h>
16 #include <__iterator/concepts.h>
17 #include <__iterator/iterator_traits.h> // iter_value_t
18 #include <cstddef>
19 #include <cstdint>
20
21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22 # pragma GCC system_header
23 #endif
24
25 _LIBCPP_BEGIN_NAMESPACE_STD
26
27 #if _LIBCPP_STD_VER >= 20
28
29 namespace __format {
30
31 template <contiguous_iterator _Iterator>
32 struct _LIBCPP_TEMPLATE_VIS __parse_number_result {
33 _Iterator __last;
34 uint32_t __value;
35 };
36
37 template <contiguous_iterator _Iterator>
38 __parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>;
39
40 template <contiguous_iterator _Iterator>
41 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
42 __parse_number(_Iterator __begin, _Iterator __end);
43
44 /**
45 * The maximum value of a numeric argument.
46 *
47 * This is used for:
48 * * arg-id
49 * * width as value or arg-id.
50 * * precision as value or arg-id.
51 *
52 * The value is compatible with the maximum formatting width and precision
53 * using the `%*` syntax on a 32-bit system.
54 */
55 inline constexpr uint32_t __number_max = INT32_MAX;
56
57 namespace __detail {
58 template <contiguous_iterator _Iterator>
59 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
__parse_zero(_Iterator __begin,_Iterator,auto & __parse_ctx)60 __parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) {
61 __parse_ctx.check_arg_id(0);
62 return {++__begin, 0}; // can never be larger than the maximum.
63 }
64
65 template <contiguous_iterator _Iterator>
66 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
__parse_automatic(_Iterator __begin,_Iterator,auto & __parse_ctx)67 __parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) {
68 size_t __value = __parse_ctx.next_arg_id();
69 _LIBCPP_ASSERT_UNCATEGORIZED(
70 __value <= __number_max,
71 "Compilers don't support this number of arguments");
72
73 return {__begin, uint32_t(__value)};
74 }
75
76 template <contiguous_iterator _Iterator>
77 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
__parse_manual(_Iterator __begin,_Iterator __end,auto & __parse_ctx)78 __parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) {
79 __parse_number_result<_Iterator> __r = __format::__parse_number(__begin, __end);
80 __parse_ctx.check_arg_id(__r.__value);
81 return __r;
82 }
83
84 } // namespace __detail
85
86 /**
87 * Parses a number.
88 *
89 * The number is used for the 31-bit values @em width and @em precision. This
90 * allows a maximum value of 2147483647.
91 */
92 template <contiguous_iterator _Iterator>
93 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
__parse_number(_Iterator __begin,_Iterator __end_input)94 __parse_number(_Iterator __begin, _Iterator __end_input) {
95 using _CharT = iter_value_t<_Iterator>;
96 static_assert(__format::__number_max == INT32_MAX,
97 "The algorithm is implemented based on this value.");
98 /*
99 * Limit the input to 9 digits, otherwise we need two checks during every
100 * iteration:
101 * - Are we at the end of the input?
102 * - Does the value exceed width of an uint32_t? (Switching to uint64_t would
103 * have the same issue, but with a higher maximum.)
104 */
105 _Iterator __end = __end_input - __begin > 9 ? __begin + 9 : __end_input;
106 uint32_t __value = *__begin - _CharT('0');
107 while (++__begin != __end) {
108 if (*__begin < _CharT('0') || *__begin > _CharT('9'))
109 return {__begin, __value};
110
111 __value = __value * 10 + *__begin - _CharT('0');
112 }
113
114 if (__begin != __end_input && *__begin >= _CharT('0') &&
115 *__begin <= _CharT('9')) {
116
117 /*
118 * There are more than 9 digits, do additional validations:
119 * - Does the 10th digit exceed the maximum allowed value?
120 * - Are there more than 10 digits?
121 * (More than 10 digits always overflows the maximum.)
122 */
123 uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0');
124 if (__v > __number_max ||
125 (__begin != __end_input && *__begin >= _CharT('0') &&
126 *__begin <= _CharT('9')))
127 std::__throw_format_error("The numeric value of the format specifier is too large");
128
129 __value = __v;
130 }
131
132 return {__begin, __value};
133 }
134
135 /**
136 * Multiplexer for all parse functions.
137 *
138 * The parser will return a pointer beyond the last consumed character. This
139 * should be the closing '}' of the arg-id.
140 */
141 template <contiguous_iterator _Iterator>
142 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
__parse_arg_id(_Iterator __begin,_Iterator __end,auto & __parse_ctx)143 __parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) {
144 using _CharT = iter_value_t<_Iterator>;
145 switch (*__begin) {
146 case _CharT('0'):
147 return __detail::__parse_zero(__begin, __end, __parse_ctx);
148
149 case _CharT(':'):
150 // This case is conditionally valid. It's allowed in an arg-id in the
151 // replacement-field, but not in the std-format-spec. The caller can
152 // provide a better diagnostic, so accept it here unconditionally.
153 case _CharT('}'):
154 return __detail::__parse_automatic(__begin, __end, __parse_ctx);
155 }
156 if (*__begin < _CharT('0') || *__begin > _CharT('9'))
157 std::__throw_format_error("The argument index starts with an invalid character");
158
159 return __detail::__parse_manual(__begin, __end, __parse_ctx);
160 }
161
162 } // namespace __format
163
164 #endif //_LIBCPP_STD_VER >= 20
165
166 _LIBCPP_END_NAMESPACE_STD
167
168 #endif // _LIBCPP___FORMAT_FORMAT_STRING_H
169