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> 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> 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> 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> 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> 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