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 <cstddef> 17 #include <cstdint> 18 19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20 # pragma GCC system_header 21 # pragma clang include_instead(<format>) 22 #endif 23 24 _LIBCPP_BEGIN_NAMESPACE_STD 25 26 #if _LIBCPP_STD_VER > 17 27 28 // TODO FMT Remove this once we require compilers with proper C++20 support. 29 // If the compiler has no concepts support, the format header will be disabled. 30 // Without concepts support enable_if needs to be used and that too much effort 31 // to support compilers with partial C++20 support. 32 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) 33 34 namespace __format { 35 36 template <class _CharT> 37 struct _LIBCPP_TEMPLATE_VIS __parse_number_result { 38 const _CharT* __ptr; 39 uint32_t __value; 40 }; 41 42 template <class _CharT> 43 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 44 __parse_number(const _CharT* __begin, const _CharT* __end); 45 46 /** 47 * The maximum value of a numeric argument. 48 * 49 * This is used for: 50 * * arg-id 51 * * width as value or arg-id. 52 * * precision as value or arg-id. 53 * 54 * The value is compatible with the maximum formatting width and precision 55 * using the `%*` syntax on a 32-bit system. 56 */ 57 inline constexpr uint32_t __number_max = INT32_MAX; 58 59 namespace __detail { 60 template <class _CharT> 61 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 62 __parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { 63 __parse_ctx.check_arg_id(0); 64 return {++__begin, 0}; // can never be larger than the maximum. 65 } 66 67 template <class _CharT> 68 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 69 __parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { 70 size_t __value = __parse_ctx.next_arg_id(); 71 _LIBCPP_ASSERT(__value <= __number_max, 72 "Compilers don't support this number of arguments"); 73 74 return {__begin, uint32_t(__value)}; 75 } 76 77 template <class _CharT> 78 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 79 __parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { 80 __parse_number_result<_CharT> __r = __parse_number(__begin, __end); 81 __parse_ctx.check_arg_id(__r.__value); 82 return __r; 83 } 84 85 } // namespace __detail 86 87 /** 88 * Parses a number. 89 * 90 * The number is used for the 31-bit values @em width and @em precision. This 91 * allows a maximum value of 2147483647. 92 */ 93 template <class _CharT> 94 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 95 __parse_number(const _CharT* __begin, const _CharT* __end_input) { 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 const _CharT* __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 __throw_format_error("The numeric value of the format-spec 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 <class _CharT> 142 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 143 __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { 144 switch (*__begin) { 145 case _CharT('0'): 146 return __detail::__parse_zero(__begin, __end, __parse_ctx); 147 148 case _CharT(':'): 149 // This case is conditionally valid. It's allowed in an arg-id in the 150 // replacement-field, but not in the std-format-spec. The caller can 151 // provide a better diagnostic, so accept it here unconditionally. 152 case _CharT('}'): 153 return __detail::__parse_automatic(__begin, __end, __parse_ctx); 154 } 155 if (*__begin < _CharT('0') || *__begin > _CharT('9')) 156 __throw_format_error( 157 "The arg-id of the format-spec starts with an invalid character"); 158 159 return __detail::__parse_manual(__begin, __end, __parse_ctx); 160 } 161 162 } // namespace __format 163 164 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 165 166 #endif //_LIBCPP_STD_VER > 17 167 168 _LIBCPP_END_NAMESPACE_STD 169 170 #endif // _LIBCPP___FORMAT_FORMAT_STRING_H 171