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