File indexing completed on 2026-05-03 08:13:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___FORMAT_FORMAT_STRING_H
0011 #define _LIBCPP___FORMAT_FORMAT_STRING_H
0012
0013 #include <__assert>
0014 #include <__config>
0015 #include <__cstddef/size_t.h>
0016 #include <__format/format_error.h>
0017 #include <__iterator/concepts.h>
0018 #include <__iterator/iterator_traits.h> // iter_value_t
0019 #include <cstdint>
0020
0021 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0022 # pragma GCC system_header
0023 #endif
0024
0025 _LIBCPP_BEGIN_NAMESPACE_STD
0026
0027 #if _LIBCPP_STD_VER >= 20
0028
0029 namespace __format {
0030
0031 template <contiguous_iterator _Iterator>
0032 struct _LIBCPP_TEMPLATE_VIS __parse_number_result {
0033 _Iterator __last;
0034 uint32_t __value;
0035 };
0036
0037 template <contiguous_iterator _Iterator>
0038 __parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>;
0039
0040 template <contiguous_iterator _Iterator>
0041 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> __parse_number(_Iterator __begin, _Iterator __end);
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 inline constexpr uint32_t __number_max = INT32_MAX;
0055
0056 namespace __detail {
0057 template <contiguous_iterator _Iterator>
0058 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0059 __parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) {
0060 __parse_ctx.check_arg_id(0);
0061 return {++__begin, 0};
0062 }
0063
0064 template <contiguous_iterator _Iterator>
0065 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0066 __parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) {
0067 size_t __value = __parse_ctx.next_arg_id();
0068 _LIBCPP_ASSERT_UNCATEGORIZED(__value <= __number_max, "Compilers don't support this number of arguments");
0069
0070 return {__begin, uint32_t(__value)};
0071 }
0072
0073 template <contiguous_iterator _Iterator>
0074 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0075 __parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) {
0076 __parse_number_result<_Iterator> __r = __format::__parse_number(__begin, __end);
0077 __parse_ctx.check_arg_id(__r.__value);
0078 return __r;
0079 }
0080
0081 }
0082
0083
0084
0085
0086
0087
0088
0089 template <contiguous_iterator _Iterator>
0090 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0091 __parse_number(_Iterator __begin, _Iterator __end_input) {
0092 using _CharT = iter_value_t<_Iterator>;
0093 static_assert(__format::__number_max == INT32_MAX, "The algorithm is implemented based on this value.");
0094
0095
0096
0097
0098
0099
0100
0101 _Iterator __end = __end_input - __begin > 9 ? __begin + 9 : __end_input;
0102 uint32_t __value = *__begin - _CharT('0');
0103 while (++__begin != __end) {
0104 if (*__begin < _CharT('0') || *__begin > _CharT('9'))
0105 return {__begin, __value};
0106
0107 __value = __value * 10 + *__begin - _CharT('0');
0108 }
0109
0110 if (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9')) {
0111
0112
0113
0114
0115
0116
0117 uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0');
0118 if (__v > __number_max || (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9')))
0119 std::__throw_format_error("The numeric value of the format specifier is too large");
0120
0121 __value = __v;
0122 }
0123
0124 return {__begin, __value};
0125 }
0126
0127
0128
0129
0130
0131
0132
0133 template <contiguous_iterator _Iterator>
0134 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0135 __parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) {
0136 using _CharT = iter_value_t<_Iterator>;
0137 switch (*__begin) {
0138 case _CharT('0'):
0139 return __detail::__parse_zero(__begin, __end, __parse_ctx);
0140
0141 case _CharT(':'):
0142
0143
0144
0145 case _CharT('}'):
0146 return __detail::__parse_automatic(__begin, __end, __parse_ctx);
0147 }
0148 if (*__begin < _CharT('0') || *__begin > _CharT('9'))
0149 std::__throw_format_error("The argument index starts with an invalid character");
0150
0151 return __detail::__parse_manual(__begin, __end, __parse_ctx);
0152 }
0153
0154 }
0155
0156 #endif
0157
0158 _LIBCPP_END_NAMESPACE_STD
0159
0160 #endif