1d7444d9fSMark de Wever // -*- C++ -*- 2d7444d9fSMark de Wever //===----------------------------------------------------------------------===// 3d7444d9fSMark de Wever // 4d7444d9fSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5d7444d9fSMark de Wever // See https://llvm.org/LICENSE.txt for license information. 6d7444d9fSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7d7444d9fSMark de Wever // 8d7444d9fSMark de Wever //===----------------------------------------------------------------------===// 9d7444d9fSMark de Wever 10d7444d9fSMark de Wever #ifndef _LIBCPP___FORMAT_FORMAT_STRING_H 11d7444d9fSMark de Wever #define _LIBCPP___FORMAT_FORMAT_STRING_H 12d7444d9fSMark de Wever 13f87aa19bSLouis Dionne #include <__assert> 14d7444d9fSMark de Wever #include <__config> 15*e99c4906SNikolas Klauser #include <__cstddef/size_t.h> 16d7444d9fSMark de Wever #include <__format/format_error.h> 171562e514SLouis Dionne #include <__iterator/concepts.h> 18d5ce68afSIan Anderson #include <__iterator/iterator_traits.h> // iter_value_t 19d7444d9fSMark de Wever #include <cstdint> 20d7444d9fSMark de Wever 21d7444d9fSMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22d7444d9fSMark de Wever # pragma GCC system_header 23d7444d9fSMark de Wever #endif 24d7444d9fSMark de Wever 25d7444d9fSMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD 26d7444d9fSMark de Wever 274f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 28d7444d9fSMark de Wever 29d7444d9fSMark de Wever namespace __format { 30d7444d9fSMark de Wever 311562e514SLouis Dionne template <contiguous_iterator _Iterator> 32d7444d9fSMark de Wever struct _LIBCPP_TEMPLATE_VIS __parse_number_result { 331562e514SLouis Dionne _Iterator __last; 34d7444d9fSMark de Wever uint32_t __value; 35d7444d9fSMark de Wever }; 36d7444d9fSMark de Wever 371562e514SLouis Dionne template <contiguous_iterator _Iterator> 381562e514SLouis Dionne __parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>; 39261b5abfSMark de Wever 401562e514SLouis Dionne template <contiguous_iterator _Iterator> 419783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> __parse_number(_Iterator __begin, _Iterator __end); 42d7444d9fSMark de Wever 43d7444d9fSMark de Wever /** 44d7444d9fSMark de Wever * The maximum value of a numeric argument. 45d7444d9fSMark de Wever * 46d7444d9fSMark de Wever * This is used for: 47d7444d9fSMark de Wever * * arg-id 48d7444d9fSMark de Wever * * width as value or arg-id. 49d7444d9fSMark de Wever * * precision as value or arg-id. 50d7444d9fSMark de Wever * 51d7444d9fSMark de Wever * The value is compatible with the maximum formatting width and precision 52d7444d9fSMark de Wever * using the `%*` syntax on a 32-bit system. 53d7444d9fSMark de Wever */ 54d7444d9fSMark de Wever inline constexpr uint32_t __number_max = INT32_MAX; 55d7444d9fSMark de Wever 56d7444d9fSMark de Wever namespace __detail { 571562e514SLouis Dionne template <contiguous_iterator _Iterator> 581562e514SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> 591562e514SLouis Dionne __parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) { 60d7444d9fSMark de Wever __parse_ctx.check_arg_id(0); 61d7444d9fSMark de Wever return {++__begin, 0}; // can never be larger than the maximum. 62d7444d9fSMark de Wever } 63d7444d9fSMark de Wever 641562e514SLouis Dionne template <contiguous_iterator _Iterator> 651562e514SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> 661562e514SLouis Dionne __parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) { 67d7444d9fSMark de Wever size_t __value = __parse_ctx.next_arg_id(); 689783f28cSLouis Dionne _LIBCPP_ASSERT_UNCATEGORIZED(__value <= __number_max, "Compilers don't support this number of arguments"); 69d7444d9fSMark de Wever 70d7444d9fSMark de Wever return {__begin, uint32_t(__value)}; 71d7444d9fSMark de Wever } 72d7444d9fSMark de Wever 731562e514SLouis Dionne template <contiguous_iterator _Iterator> 741562e514SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> 751562e514SLouis Dionne __parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { 761562e514SLouis Dionne __parse_number_result<_Iterator> __r = __format::__parse_number(__begin, __end); 77d7444d9fSMark de Wever __parse_ctx.check_arg_id(__r.__value); 78d7444d9fSMark de Wever return __r; 79d7444d9fSMark de Wever } 80d7444d9fSMark de Wever 81d7444d9fSMark de Wever } // namespace __detail 82d7444d9fSMark de Wever 83d7444d9fSMark de Wever /** 84d7444d9fSMark de Wever * Parses a number. 85d7444d9fSMark de Wever * 86d7444d9fSMark de Wever * The number is used for the 31-bit values @em width and @em precision. This 87d7444d9fSMark de Wever * allows a maximum value of 2147483647. 88d7444d9fSMark de Wever */ 891562e514SLouis Dionne template <contiguous_iterator _Iterator> 901562e514SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> 911562e514SLouis Dionne __parse_number(_Iterator __begin, _Iterator __end_input) { 921562e514SLouis Dionne using _CharT = iter_value_t<_Iterator>; 939783f28cSLouis Dionne static_assert(__format::__number_max == INT32_MAX, "The algorithm is implemented based on this value."); 94d7444d9fSMark de Wever /* 95d7444d9fSMark de Wever * Limit the input to 9 digits, otherwise we need two checks during every 96d7444d9fSMark de Wever * iteration: 97d7444d9fSMark de Wever * - Are we at the end of the input? 98d7444d9fSMark de Wever * - Does the value exceed width of an uint32_t? (Switching to uint64_t would 99d7444d9fSMark de Wever * have the same issue, but with a higher maximum.) 100d7444d9fSMark de Wever */ 1011562e514SLouis Dionne _Iterator __end = __end_input - __begin > 9 ? __begin + 9 : __end_input; 102d7444d9fSMark de Wever uint32_t __value = *__begin - _CharT('0'); 103d7444d9fSMark de Wever while (++__begin != __end) { 104d7444d9fSMark de Wever if (*__begin < _CharT('0') || *__begin > _CharT('9')) 105d7444d9fSMark de Wever return {__begin, __value}; 106d7444d9fSMark de Wever 107d7444d9fSMark de Wever __value = __value * 10 + *__begin - _CharT('0'); 108d7444d9fSMark de Wever } 109d7444d9fSMark de Wever 1109783f28cSLouis Dionne if (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9')) { 111d7444d9fSMark de Wever /* 112d7444d9fSMark de Wever * There are more than 9 digits, do additional validations: 113d7444d9fSMark de Wever * - Does the 10th digit exceed the maximum allowed value? 114d7444d9fSMark de Wever * - Are there more than 10 digits? 115d7444d9fSMark de Wever * (More than 10 digits always overflows the maximum.) 116d7444d9fSMark de Wever */ 117d7444d9fSMark de Wever uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0'); 1189783f28cSLouis Dionne if (__v > __number_max || (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9'))) 119402eb2efSMark de Wever std::__throw_format_error("The numeric value of the format specifier is too large"); 120d7444d9fSMark de Wever 121d7444d9fSMark de Wever __value = __v; 122d7444d9fSMark de Wever } 123d7444d9fSMark de Wever 124d7444d9fSMark de Wever return {__begin, __value}; 125d7444d9fSMark de Wever } 126d7444d9fSMark de Wever 127d7444d9fSMark de Wever /** 128d7444d9fSMark de Wever * Multiplexer for all parse functions. 129d7444d9fSMark de Wever * 130d7444d9fSMark de Wever * The parser will return a pointer beyond the last consumed character. This 131d7444d9fSMark de Wever * should be the closing '}' of the arg-id. 132d7444d9fSMark de Wever */ 1331562e514SLouis Dionne template <contiguous_iterator _Iterator> 1341562e514SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> 1351562e514SLouis Dionne __parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) { 1361562e514SLouis Dionne using _CharT = iter_value_t<_Iterator>; 137d7444d9fSMark de Wever switch (*__begin) { 138d7444d9fSMark de Wever case _CharT('0'): 139d7444d9fSMark de Wever return __detail::__parse_zero(__begin, __end, __parse_ctx); 140d7444d9fSMark de Wever 141d7444d9fSMark de Wever case _CharT(':'): 142d7444d9fSMark de Wever // This case is conditionally valid. It's allowed in an arg-id in the 143d7444d9fSMark de Wever // replacement-field, but not in the std-format-spec. The caller can 144d7444d9fSMark de Wever // provide a better diagnostic, so accept it here unconditionally. 145d7444d9fSMark de Wever case _CharT('}'): 146d7444d9fSMark de Wever return __detail::__parse_automatic(__begin, __end, __parse_ctx); 147d7444d9fSMark de Wever } 148d7444d9fSMark de Wever if (*__begin < _CharT('0') || *__begin > _CharT('9')) 149402eb2efSMark de Wever std::__throw_format_error("The argument index starts with an invalid character"); 150d7444d9fSMark de Wever 151d7444d9fSMark de Wever return __detail::__parse_manual(__begin, __end, __parse_ctx); 152d7444d9fSMark de Wever } 153d7444d9fSMark de Wever 154d7444d9fSMark de Wever } // namespace __format 155d7444d9fSMark de Wever 1564f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20 157d7444d9fSMark de Wever 158d7444d9fSMark de Wever _LIBCPP_END_NAMESPACE_STD 159d7444d9fSMark de Wever 160d7444d9fSMark de Wever #endif // _LIBCPP___FORMAT_FORMAT_STRING_H 161