2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___FORMAT_FORMAT_STRING_H
11 #define _LIBCPP___FORMAT_FORMAT_STRING_H
15 #include <__format/format_error.h>
16 #include <__iterator/concepts.h>
17 #include <__iterator/iterator_traits.h> // iter_value_t
21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22 # pragma GCC system_header
25 _LIBCPP_BEGIN_NAMESPACE_STD
27 #if _LIBCPP_STD_VER >= 20
31 template <contiguous_iterator _Iterator
>
32 struct _LIBCPP_TEMPLATE_VIS __parse_number_result
{
37 template <contiguous_iterator _Iterator
>
38 __parse_number_result(_Iterator
, uint32_t) -> __parse_number_result
<_Iterator
>;
40 template <contiguous_iterator _Iterator
>
41 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
42 __parse_number(_Iterator __begin
, _Iterator __end
);
45 * The maximum value of a numeric argument.
49 * * width as value or arg-id.
50 * * precision as value or arg-id.
52 * The value is compatible with the maximum formatting width and precision
53 * using the `%*` syntax on a 32-bit system.
55 inline constexpr uint32_t __number_max
= INT32_MAX
;
58 template <contiguous_iterator _Iterator
>
59 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
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.
65 template <contiguous_iterator _Iterator
>
66 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
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");
73 return {__begin
, uint32_t(__value
)};
76 template <contiguous_iterator _Iterator
>
77 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
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
);
84 } // namespace __detail
89 * The number is used for the 31-bit values @em width and @em precision. This
90 * allows a maximum value of 2147483647.
92 template <contiguous_iterator _Iterator
>
93 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
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.");
99 * Limit the input to 9 digits, otherwise we need two checks during every
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.)
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
};
111 __value
= __value
* 10 + *__begin
- _CharT('0');
114 if (__begin
!= __end_input
&& *__begin
>= _CharT('0') &&
115 *__begin
<= _CharT('9')) {
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.)
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");
132 return {__begin
, __value
};
136 * Multiplexer for all parse functions.
138 * The parser will return a pointer beyond the last consumed character. This
139 * should be the closing '}' of the arg-id.
141 template <contiguous_iterator _Iterator
>
142 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
143 __parse_arg_id(_Iterator __begin
, _Iterator __end
, auto& __parse_ctx
) {
144 using _CharT
= iter_value_t
<_Iterator
>;
147 return __detail::__parse_zero(__begin
, __end
, __parse_ctx
);
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.
154 return __detail::__parse_automatic(__begin
, __end
, __parse_ctx
);
156 if (*__begin
< _CharT('0') || *__begin
> _CharT('9'))
157 std::__throw_format_error("The argument index starts with an invalid character");
159 return __detail::__parse_manual(__begin
, __end
, __parse_ctx
);
162 } // namespace __format
164 #endif //_LIBCPP_STD_VER >= 20
166 _LIBCPP_END_NAMESPACE_STD
168 #endif // _LIBCPP___FORMAT_FORMAT_STRING_H