Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:29

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___CXX03___FORMAT_FORMAT_STRING_H
0011 #define _LIBCPP___CXX03___FORMAT_FORMAT_STRING_H
0012 
0013 #include <__cxx03/__assert>
0014 #include <__cxx03/__config>
0015 #include <__cxx03/__format/format_error.h>
0016 #include <__cxx03/__iterator/concepts.h>
0017 #include <__cxx03/__iterator/iterator_traits.h> // iter_value_t
0018 #include <__cxx03/cstddef>
0019 #include <__cxx03/cstdint>
0020 
0021 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0022 #  pragma GCC system_header
0023 #endif
0024 
0025 _LIBCPP_BEGIN_NAMESPACE_STD
0026 
0027 #if _LIBCPP_STD_VER >= 20
0028 
0029 namespace __format {
0030 
0031 template <contiguous_iterator _Iterator>
0032 struct _LIBCPP_TEMPLATE_VIS __parse_number_result {
0033   _Iterator __last;
0034   uint32_t __value;
0035 };
0036 
0037 template <contiguous_iterator _Iterator>
0038 __parse_number_result(_Iterator, uint32_t) -> __parse_number_result<_Iterator>;
0039 
0040 template <contiguous_iterator _Iterator>
0041 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator> __parse_number(_Iterator __begin, _Iterator __end);
0042 
0043 /**
0044  * The maximum value of a numeric argument.
0045  *
0046  * This is used for:
0047  * * arg-id
0048  * * width as value or arg-id.
0049  * * precision as value or arg-id.
0050  *
0051  * The value is compatible with the maximum formatting width and precision
0052  * using the `%*` syntax on a 32-bit system.
0053  */
0054 inline constexpr uint32_t __number_max = INT32_MAX;
0055 
0056 namespace __detail {
0057 template <contiguous_iterator _Iterator>
0058 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0059 __parse_zero(_Iterator __begin, _Iterator, auto& __parse_ctx) {
0060   __parse_ctx.check_arg_id(0);
0061   return {++__begin, 0}; // can never be larger than the maximum.
0062 }
0063 
0064 template <contiguous_iterator _Iterator>
0065 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0066 __parse_automatic(_Iterator __begin, _Iterator, auto& __parse_ctx) {
0067   size_t __value = __parse_ctx.next_arg_id();
0068   _LIBCPP_ASSERT_UNCATEGORIZED(__value <= __number_max, "Compilers don't support this number of arguments");
0069 
0070   return {__begin, uint32_t(__value)};
0071 }
0072 
0073 template <contiguous_iterator _Iterator>
0074 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0075 __parse_manual(_Iterator __begin, _Iterator __end, auto& __parse_ctx) {
0076   __parse_number_result<_Iterator> __r = __format::__parse_number(__begin, __end);
0077   __parse_ctx.check_arg_id(__r.__value);
0078   return __r;
0079 }
0080 
0081 } // namespace __detail
0082 
0083 /**
0084  * Parses a number.
0085  *
0086  * The number is used for the 31-bit values @em width and @em precision. This
0087  * allows a maximum value of 2147483647.
0088  */
0089 template <contiguous_iterator _Iterator>
0090 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0091 __parse_number(_Iterator __begin, _Iterator __end_input) {
0092   using _CharT = iter_value_t<_Iterator>;
0093   static_assert(__format::__number_max == INT32_MAX, "The algorithm is implemented based on this value.");
0094   /*
0095    * Limit the input to 9 digits, otherwise we need two checks during every
0096    * iteration:
0097    * - Are we at the end of the input?
0098    * - Does the value exceed width of an uint32_t? (Switching to uint64_t would
0099    *   have the same issue, but with a higher maximum.)
0100    */
0101   _Iterator __end  = __end_input - __begin > 9 ? __begin + 9 : __end_input;
0102   uint32_t __value = *__begin - _CharT('0');
0103   while (++__begin != __end) {
0104     if (*__begin < _CharT('0') || *__begin > _CharT('9'))
0105       return {__begin, __value};
0106 
0107     __value = __value * 10 + *__begin - _CharT('0');
0108   }
0109 
0110   if (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9')) {
0111     /*
0112      * There are more than 9 digits, do additional validations:
0113      * - Does the 10th digit exceed the maximum allowed value?
0114      * - Are there more than 10 digits?
0115      * (More than 10 digits always overflows the maximum.)
0116      */
0117     uint64_t __v = uint64_t(__value) * 10 + *__begin++ - _CharT('0');
0118     if (__v > __number_max || (__begin != __end_input && *__begin >= _CharT('0') && *__begin <= _CharT('9')))
0119       std::__throw_format_error("The numeric value of the format specifier is too large");
0120 
0121     __value = __v;
0122   }
0123 
0124   return {__begin, __value};
0125 }
0126 
0127 /**
0128  * Multiplexer for all parse functions.
0129  *
0130  * The parser will return a pointer beyond the last consumed character. This
0131  * should be the closing '}' of the arg-id.
0132  */
0133 template <contiguous_iterator _Iterator>
0134 _LIBCPP_HIDE_FROM_ABI constexpr __parse_number_result<_Iterator>
0135 __parse_arg_id(_Iterator __begin, _Iterator __end, auto& __parse_ctx) {
0136   using _CharT = iter_value_t<_Iterator>;
0137   switch (*__begin) {
0138   case _CharT('0'):
0139     return __detail::__parse_zero(__begin, __end, __parse_ctx);
0140 
0141   case _CharT(':'):
0142     // This case is conditionally valid. It's allowed in an arg-id in the
0143     // replacement-field, but not in the std-format-spec. The caller can
0144     // provide a better diagnostic, so accept it here unconditionally.
0145   case _CharT('}'):
0146     return __detail::__parse_automatic(__begin, __end, __parse_ctx);
0147   }
0148   if (*__begin < _CharT('0') || *__begin > _CharT('9'))
0149     std::__throw_format_error("The argument index starts with an invalid character");
0150 
0151   return __detail::__parse_manual(__begin, __end, __parse_ctx);
0152 }
0153 
0154 } // namespace __format
0155 
0156 #endif //_LIBCPP_STD_VER >= 20
0157 
0158 _LIBCPP_END_NAMESPACE_STD
0159 
0160 #endif // _LIBCPP___CXX03___FORMAT_FORMAT_STRING_H