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 <__config> 14 #include <__debug> 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 #endif 22 23 _LIBCPP_PUSH_MACROS 24 #include <__undef_macros> 25 26 _LIBCPP_BEGIN_NAMESPACE_STD 27 28 #if _LIBCPP_STD_VER > 17 29 30 // TODO FMT Remove this once we require compilers with proper C++20 support. 31 // If the compiler has no concepts support, the format header will be disabled. 32 // Without concepts support enable_if needs to be used and that too much effort 33 // to support compilers with partial C++20 support. 34 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) 35 36 namespace __format { 37 38 template <class _CharT> 39 struct _LIBCPP_TEMPLATE_VIS __parse_number_result { 40 const _CharT* __ptr; 41 uint32_t __value; 42 }; 43 44 template <class _CharT> 45 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 46 __parse_number(const _CharT* __begin, const _CharT* __end); 47 48 /** 49 * The maximum value of a numeric argument. 50 * 51 * This is used for: 52 * * arg-id 53 * * width as value or arg-id. 54 * * precision as value or arg-id. 55 * 56 * The value is compatible with the maximum formatting width and precision 57 * using the `%*` syntax on a 32-bit system. 58 */ 59 inline constexpr uint32_t __number_max = INT32_MAX; 60 61 namespace __detail { 62 template <class _CharT> 63 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 64 __parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { 65 __parse_ctx.check_arg_id(0); 66 return {++__begin, 0}; // can never be larger than the maximum. 67 } 68 69 template <class _CharT> 70 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 71 __parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) { 72 size_t __value = __parse_ctx.next_arg_id(); 73 _LIBCPP_ASSERT(__value <= __number_max, 74 "Compilers don't support this number of arguments"); 75 76 return {__begin, uint32_t(__value)}; 77 } 78 79 template <class _CharT> 80 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 81 __parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { 82 __parse_number_result<_CharT> __r = __parse_number(__begin, __end); 83 __parse_ctx.check_arg_id(__r.__value); 84 return __r; 85 } 86 87 } // namespace __detail 88 89 /** 90 * Parses a number. 91 * 92 * The number is used for the 31-bit values @em width and @em precision. This 93 * allows a maximum value of 2147483647. 94 */ 95 template <class _CharT> 96 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 97 __parse_number(const _CharT* __begin, const _CharT* __end_input) { 98 static_assert(__format::__number_max == INT32_MAX, 99 "The algorithm is implemented based on this value."); 100 /* 101 * Limit the input to 9 digits, otherwise we need two checks during every 102 * iteration: 103 * - Are we at the end of the input? 104 * - Does the value exceed width of an uint32_t? (Switching to uint64_t would 105 * have the same issue, but with a higher maximum.) 106 */ 107 const _CharT* __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; 108 uint32_t __value = *__begin - _CharT('0'); 109 while (++__begin != __end) { 110 if (*__begin < _CharT('0') || *__begin > _CharT('9')) 111 return {__begin, __value}; 112 113 __value = __value * 10 + *__begin - _CharT('0'); 114 } 115 116 if (__begin != __end_input && *__begin >= _CharT('0') && 117 *__begin <= _CharT('9')) { 118 119 /* 120 * There are more than 9 digits, do additional validations: 121 * - Does the 10th digit exceed the maximum allowed value? 122 * - Are there more than 10 digits? 123 * (More than 10 digits always overflows the maximum.) 124 */ 125 uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0'); 126 if (__v > __number_max || 127 (__begin != __end_input && *__begin >= _CharT('0') && 128 *__begin <= _CharT('9'))) 129 __throw_format_error("The numeric value of the format-spec is too large"); 130 131 __value = __v; 132 } 133 134 return {__begin, __value}; 135 } 136 137 /** 138 * Multiplexer for all parse functions. 139 * 140 * The parser will return a pointer beyond the last consumed character. This 141 * should be the closing '}' of the arg-id. 142 */ 143 template <class _CharT> 144 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT> 145 __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) { 146 switch (*__begin) { 147 case _CharT('0'): 148 return __detail::__parse_zero(__begin, __end, __parse_ctx); 149 150 case _CharT(':'): 151 // This case is conditionally valid. It's allowed in an arg-id in the 152 // replacement-field, but not in the std-format-spec. The caller can 153 // provide a better diagnostic, so accept it here unconditionally. 154 case _CharT('}'): 155 return __detail::__parse_automatic(__begin, __end, __parse_ctx); 156 } 157 if (*__begin < _CharT('0') || *__begin > _CharT('9')) 158 __throw_format_error( 159 "The arg-id of the format-spec starts with an invalid character"); 160 161 return __detail::__parse_manual(__begin, __end, __parse_ctx); 162 } 163 164 } // namespace __format 165 166 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) 167 168 #endif //_LIBCPP_STD_VER > 17 169 170 _LIBCPP_END_NAMESPACE_STD 171 172 _LIBCPP_POP_MACROS 173 174 #endif // _LIBCPP___FORMAT_FORMAT_STRING_H 175