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_PARSE_CONTEXT_H 11 #define _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H 12 13 #include <__config> 14 #include <__format/format_error.h> 15 #include <__type_traits/is_constant_evaluated.h> 16 #include <string_view> 17 18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 19 # pragma GCC system_header 20 #endif 21 22 _LIBCPP_BEGIN_NAMESPACE_STD 23 24 #if _LIBCPP_STD_VER >= 20 25 26 template <class _CharT> 27 class _LIBCPP_TEMPLATE_VIS basic_format_parse_context { 28 public: 29 using char_type = _CharT; 30 using const_iterator = typename basic_string_view<_CharT>::const_iterator; 31 using iterator = const_iterator; 32 33 _LIBCPP_HIDE_FROM_ABI 34 constexpr explicit basic_format_parse_context(basic_string_view<_CharT> __fmt, 35 size_t __num_args = 0) noexcept 36 : __begin_(__fmt.begin()), 37 __end_(__fmt.end()), 38 __indexing_(__unknown), 39 __next_arg_id_(0), 40 __num_args_(__num_args) {} 41 42 basic_format_parse_context(const basic_format_parse_context&) = delete; 43 basic_format_parse_context& 44 operator=(const basic_format_parse_context&) = delete; 45 begin()46 _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept { 47 return __begin_; 48 } end()49 _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept { 50 return __end_; 51 } advance_to(const_iterator __it)52 _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(const_iterator __it) { 53 __begin_ = __it; 54 } 55 next_arg_id()56 _LIBCPP_HIDE_FROM_ABI constexpr size_t next_arg_id() { 57 if (__indexing_ == __manual) 58 std::__throw_format_error("Using automatic argument numbering in manual argument numbering mode"); 59 60 if (__indexing_ == __unknown) 61 __indexing_ = __automatic; 62 63 // Throws an exception to make the expression a non core constant 64 // expression as required by: 65 // [format.parse.ctx]/8 66 // Remarks: Let cur-arg-id be the value of next_arg_id_ prior to this 67 // call. Call expressions where cur-arg-id >= num_args_ is true are not 68 // core constant expressions (7.7 [expr.const]). 69 // Note: the Throws clause [format.parse.ctx]/9 doesn't specify the 70 // behavior when id >= num_args_. 71 if (is_constant_evaluated() && __next_arg_id_ >= __num_args_) 72 std::__throw_format_error("Argument index outside the valid range"); 73 74 return __next_arg_id_++; 75 } check_arg_id(size_t __id)76 _LIBCPP_HIDE_FROM_ABI constexpr void check_arg_id(size_t __id) { 77 if (__indexing_ == __automatic) 78 std::__throw_format_error("Using manual argument numbering in automatic argument numbering mode"); 79 80 if (__indexing_ == __unknown) 81 __indexing_ = __manual; 82 83 // Throws an exception to make the expression a non core constant 84 // expression as required by: 85 // [format.parse.ctx]/11 86 // Remarks: Call expressions where id >= num_args_ are not core constant 87 // expressions ([expr.const]). 88 // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the 89 // behavior when id >= num_args_. 90 if (is_constant_evaluated() && __id >= __num_args_) 91 std::__throw_format_error("Argument index outside the valid range"); 92 } 93 94 private: 95 iterator __begin_; 96 iterator __end_; 97 enum _Indexing { __unknown, __manual, __automatic }; 98 _Indexing __indexing_; 99 size_t __next_arg_id_; 100 size_t __num_args_; 101 }; 102 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_parse_context); 103 104 using format_parse_context = basic_format_parse_context<char>; 105 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 106 using wformat_parse_context = basic_format_parse_context<wchar_t>; 107 #endif 108 109 #endif //_LIBCPP_STD_VER >= 20 110 111 _LIBCPP_END_NAMESPACE_STD 112 113 #endif // _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H 114