1*4bdff4beSrobert // -*- C++ -*-
2*4bdff4beSrobert //===----------------------------------------------------------------------===//
3*4bdff4beSrobert //
4*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
6*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4bdff4beSrobert //
8*4bdff4beSrobert //===----------------------------------------------------------------------===//
9*4bdff4beSrobert
10*4bdff4beSrobert #ifndef _LIBCPP___FORMAT_FORMAT_STRING_H
11*4bdff4beSrobert #define _LIBCPP___FORMAT_FORMAT_STRING_H
12*4bdff4beSrobert
13*4bdff4beSrobert #include <__assert>
14*4bdff4beSrobert #include <__config>
15*4bdff4beSrobert #include <__format/format_error.h>
16*4bdff4beSrobert #include <cstddef>
17*4bdff4beSrobert #include <cstdint>
18*4bdff4beSrobert
19*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20*4bdff4beSrobert # pragma GCC system_header
21*4bdff4beSrobert #endif
22*4bdff4beSrobert
23*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
24*4bdff4beSrobert
25*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
26*4bdff4beSrobert
27*4bdff4beSrobert namespace __format {
28*4bdff4beSrobert
29*4bdff4beSrobert template <class _CharT>
30*4bdff4beSrobert struct _LIBCPP_TEMPLATE_VIS __parse_number_result {
31*4bdff4beSrobert const _CharT* __ptr;
32*4bdff4beSrobert uint32_t __value;
33*4bdff4beSrobert };
34*4bdff4beSrobert
35*4bdff4beSrobert template <class _CharT>
36*4bdff4beSrobert __parse_number_result(const _CharT*, uint32_t) -> __parse_number_result<_CharT>;
37*4bdff4beSrobert
38*4bdff4beSrobert template <class _CharT>
39*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT>
40*4bdff4beSrobert __parse_number(const _CharT* __begin, const _CharT* __end);
41*4bdff4beSrobert
42*4bdff4beSrobert /**
43*4bdff4beSrobert * The maximum value of a numeric argument.
44*4bdff4beSrobert *
45*4bdff4beSrobert * This is used for:
46*4bdff4beSrobert * * arg-id
47*4bdff4beSrobert * * width as value or arg-id.
48*4bdff4beSrobert * * precision as value or arg-id.
49*4bdff4beSrobert *
50*4bdff4beSrobert * The value is compatible with the maximum formatting width and precision
51*4bdff4beSrobert * using the `%*` syntax on a 32-bit system.
52*4bdff4beSrobert */
53*4bdff4beSrobert inline constexpr uint32_t __number_max = INT32_MAX;
54*4bdff4beSrobert
55*4bdff4beSrobert namespace __detail {
56*4bdff4beSrobert template <class _CharT>
57*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT>
__parse_zero(const _CharT * __begin,const _CharT *,auto & __parse_ctx)58*4bdff4beSrobert __parse_zero(const _CharT* __begin, const _CharT*, auto& __parse_ctx) {
59*4bdff4beSrobert __parse_ctx.check_arg_id(0);
60*4bdff4beSrobert return {++__begin, 0}; // can never be larger than the maximum.
61*4bdff4beSrobert }
62*4bdff4beSrobert
63*4bdff4beSrobert template <class _CharT>
64*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT>
__parse_automatic(const _CharT * __begin,const _CharT *,auto & __parse_ctx)65*4bdff4beSrobert __parse_automatic(const _CharT* __begin, const _CharT*, auto& __parse_ctx) {
66*4bdff4beSrobert size_t __value = __parse_ctx.next_arg_id();
67*4bdff4beSrobert _LIBCPP_ASSERT(__value <= __number_max,
68*4bdff4beSrobert "Compilers don't support this number of arguments");
69*4bdff4beSrobert
70*4bdff4beSrobert return {__begin, uint32_t(__value)};
71*4bdff4beSrobert }
72*4bdff4beSrobert
73*4bdff4beSrobert template <class _CharT>
74*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT>
__parse_manual(const _CharT * __begin,const _CharT * __end,auto & __parse_ctx)75*4bdff4beSrobert __parse_manual(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
76*4bdff4beSrobert __parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end);
77*4bdff4beSrobert __parse_ctx.check_arg_id(__r.__value);
78*4bdff4beSrobert return __r;
79*4bdff4beSrobert }
80*4bdff4beSrobert
81*4bdff4beSrobert } // namespace __detail
82*4bdff4beSrobert
83*4bdff4beSrobert /**
84*4bdff4beSrobert * Parses a number.
85*4bdff4beSrobert *
86*4bdff4beSrobert * The number is used for the 31-bit values @em width and @em precision. This
87*4bdff4beSrobert * allows a maximum value of 2147483647.
88*4bdff4beSrobert */
89*4bdff4beSrobert template <class _CharT>
90*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT>
__parse_number(const _CharT * __begin,const _CharT * __end_input)91*4bdff4beSrobert __parse_number(const _CharT* __begin, const _CharT* __end_input) {
92*4bdff4beSrobert static_assert(__format::__number_max == INT32_MAX,
93*4bdff4beSrobert "The algorithm is implemented based on this value.");
94*4bdff4beSrobert /*
95*4bdff4beSrobert * Limit the input to 9 digits, otherwise we need two checks during every
96*4bdff4beSrobert * iteration:
97*4bdff4beSrobert * - Are we at the end of the input?
98*4bdff4beSrobert * - Does the value exceed width of an uint32_t? (Switching to uint64_t would
99*4bdff4beSrobert * have the same issue, but with a higher maximum.)
100*4bdff4beSrobert */
101*4bdff4beSrobert const _CharT* __end = __end_input - __begin > 9 ? __begin + 9 : __end_input;
102*4bdff4beSrobert uint32_t __value = *__begin - _CharT('0');
103*4bdff4beSrobert while (++__begin != __end) {
104*4bdff4beSrobert if (*__begin < _CharT('0') || *__begin > _CharT('9'))
105*4bdff4beSrobert return {__begin, __value};
106*4bdff4beSrobert
107*4bdff4beSrobert __value = __value * 10 + *__begin - _CharT('0');
108*4bdff4beSrobert }
109*4bdff4beSrobert
110*4bdff4beSrobert if (__begin != __end_input && *__begin >= _CharT('0') &&
111*4bdff4beSrobert *__begin <= _CharT('9')) {
112*4bdff4beSrobert
113*4bdff4beSrobert /*
114*4bdff4beSrobert * There are more than 9 digits, do additional validations:
115*4bdff4beSrobert * - Does the 10th digit exceed the maximum allowed value?
116*4bdff4beSrobert * - Are there more than 10 digits?
117*4bdff4beSrobert * (More than 10 digits always overflows the maximum.)
118*4bdff4beSrobert */
119*4bdff4beSrobert uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0');
120*4bdff4beSrobert if (__v > __number_max ||
121*4bdff4beSrobert (__begin != __end_input && *__begin >= _CharT('0') &&
122*4bdff4beSrobert *__begin <= _CharT('9')))
123*4bdff4beSrobert std::__throw_format_error("The numeric value of the format-spec is too large");
124*4bdff4beSrobert
125*4bdff4beSrobert __value = __v;
126*4bdff4beSrobert }
127*4bdff4beSrobert
128*4bdff4beSrobert return {__begin, __value};
129*4bdff4beSrobert }
130*4bdff4beSrobert
131*4bdff4beSrobert /**
132*4bdff4beSrobert * Multiplexer for all parse functions.
133*4bdff4beSrobert *
134*4bdff4beSrobert * The parser will return a pointer beyond the last consumed character. This
135*4bdff4beSrobert * should be the closing '}' of the arg-id.
136*4bdff4beSrobert */
137*4bdff4beSrobert template <class _CharT>
138*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_CharT>
__parse_arg_id(const _CharT * __begin,const _CharT * __end,auto & __parse_ctx)139*4bdff4beSrobert __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
140*4bdff4beSrobert switch (*__begin) {
141*4bdff4beSrobert case _CharT('0'):
142*4bdff4beSrobert return __detail::__parse_zero(__begin, __end, __parse_ctx);
143*4bdff4beSrobert
144*4bdff4beSrobert case _CharT(':'):
145*4bdff4beSrobert // This case is conditionally valid. It's allowed in an arg-id in the
146*4bdff4beSrobert // replacement-field, but not in the std-format-spec. The caller can
147*4bdff4beSrobert // provide a better diagnostic, so accept it here unconditionally.
148*4bdff4beSrobert case _CharT('}'):
149*4bdff4beSrobert return __detail::__parse_automatic(__begin, __end, __parse_ctx);
150*4bdff4beSrobert }
151*4bdff4beSrobert if (*__begin < _CharT('0') || *__begin > _CharT('9'))
152*4bdff4beSrobert std::__throw_format_error("The arg-id of the format-spec starts with an invalid character");
153*4bdff4beSrobert
154*4bdff4beSrobert return __detail::__parse_manual(__begin, __end, __parse_ctx);
155*4bdff4beSrobert }
156*4bdff4beSrobert
157*4bdff4beSrobert } // namespace __format
158*4bdff4beSrobert
159*4bdff4beSrobert #endif //_LIBCPP_STD_VER > 17
160*4bdff4beSrobert
161*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
162*4bdff4beSrobert
163*4bdff4beSrobert #endif // _LIBCPP___FORMAT_FORMAT_STRING_H
164