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 <__cstddef/size_t.h>
16 #include <__format/format_error.h>
17 #include <__iterator/concepts.h>
18 #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
> __parse_number(_Iterator __begin
, _Iterator __end
);
44 * The maximum value of a numeric argument.
48 * * width as value or arg-id.
49 * * precision as value or arg-id.
51 * The value is compatible with the maximum formatting width and precision
52 * using the `%*` syntax on a 32-bit system.
54 inline constexpr uint32_t __number_max
= INT32_MAX
;
57 template <contiguous_iterator _Iterator
>
58 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
59 __parse_zero(_Iterator __begin
, _Iterator
, auto& __parse_ctx
) {
60 __parse_ctx
.check_arg_id(0);
61 return {++__begin
, 0}; // can never be larger than the maximum.
64 template <contiguous_iterator _Iterator
>
65 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
66 __parse_automatic(_Iterator __begin
, _Iterator
, auto& __parse_ctx
) {
67 size_t __value
= __parse_ctx
.next_arg_id();
68 _LIBCPP_ASSERT_UNCATEGORIZED(__value
<= __number_max
, "Compilers don't support this number of arguments");
70 return {__begin
, uint32_t(__value
)};
73 template <contiguous_iterator _Iterator
>
74 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
75 __parse_manual(_Iterator __begin
, _Iterator __end
, auto& __parse_ctx
) {
76 __parse_number_result
<_Iterator
> __r
= __format::__parse_number(__begin
, __end
);
77 __parse_ctx
.check_arg_id(__r
.__value
);
81 } // namespace __detail
86 * The number is used for the 31-bit values @em width and @em precision. This
87 * allows a maximum value of 2147483647.
89 template <contiguous_iterator _Iterator
>
90 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
91 __parse_number(_Iterator __begin
, _Iterator __end_input
) {
92 using _CharT
= iter_value_t
<_Iterator
>;
93 static_assert(__format::__number_max
== INT32_MAX
, "The algorithm is implemented based on this value.");
95 * Limit the input to 9 digits, otherwise we need two checks during every
97 * - Are we at the end of the input?
98 * - Does the value exceed width of an uint32_t? (Switching to uint64_t would
99 * have the same issue, but with a higher maximum.)
101 _Iterator __end
= __end_input
- __begin
> 9 ? __begin
+ 9 : __end_input
;
102 uint32_t __value
= *__begin
- _CharT('0');
103 while (++__begin
!= __end
) {
104 if (*__begin
< _CharT('0') || *__begin
> _CharT('9'))
105 return {__begin
, __value
};
107 __value
= __value
* 10 + *__begin
- _CharT('0');
110 if (__begin
!= __end_input
&& *__begin
>= _CharT('0') && *__begin
<= _CharT('9')) {
112 * There are more than 9 digits, do additional validations:
113 * - Does the 10th digit exceed the maximum allowed value?
114 * - Are there more than 10 digits?
115 * (More than 10 digits always overflows the maximum.)
117 uint64_t __v
= uint64_t(__value
) * 10 + *__begin
++ - _CharT('0');
118 if (__v
> __number_max
|| (__begin
!= __end_input
&& *__begin
>= _CharT('0') && *__begin
<= _CharT('9')))
119 std::__throw_format_error("The numeric value of the format specifier is too large");
124 return {__begin
, __value
};
128 * Multiplexer for all parse functions.
130 * The parser will return a pointer beyond the last consumed character. This
131 * should be the closing '}' of the arg-id.
133 template <contiguous_iterator _Iterator
>
134 _LIBCPP_HIDE_FROM_ABI
constexpr __parse_number_result
<_Iterator
>
135 __parse_arg_id(_Iterator __begin
, _Iterator __end
, auto& __parse_ctx
) {
136 using _CharT
= iter_value_t
<_Iterator
>;
139 return __detail::__parse_zero(__begin
, __end
, __parse_ctx
);
142 // This case is conditionally valid. It's allowed in an arg-id in the
143 // replacement-field, but not in the std-format-spec. The caller can
144 // provide a better diagnostic, so accept it here unconditionally.
146 return __detail::__parse_automatic(__begin
, __end
, __parse_ctx
);
148 if (*__begin
< _CharT('0') || *__begin
> _CharT('9'))
149 std::__throw_format_error("The argument index starts with an invalid character");
151 return __detail::__parse_manual(__begin
, __end
, __parse_ctx
);
154 } // namespace __format
156 #endif // _LIBCPP_STD_VER >= 20
158 _LIBCPP_END_NAMESPACE_STD
160 #endif // _LIBCPP___FORMAT_FORMAT_STRING_H