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 <string_view> 16 17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 18 #pragma GCC system_header 19 #endif 20 21 _LIBCPP_PUSH_MACROS 22 #include <__undef_macros> 23 24 _LIBCPP_BEGIN_NAMESPACE_STD 25 26 #if _LIBCPP_STD_VER > 17 27 28 // TODO FMT Remove this once we require compilers with proper C++20 support. 29 // If the compiler has no concepts support, the format header will be disabled. 30 // Without concepts support enable_if needs to be used and that too much effort 31 // to support compilers with partial C++20 support. 32 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) && \ 33 !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) 34 35 template <class _CharT> 36 class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_parse_context { 37 public: 38 using char_type = _CharT; 39 using const_iterator = typename basic_string_view<_CharT>::const_iterator; 40 using iterator = const_iterator; 41 42 _LIBCPP_HIDE_FROM_ABI 43 constexpr explicit basic_format_parse_context(basic_string_view<_CharT> __fmt, 44 size_t __num_args = 0) noexcept 45 : __begin_(__fmt.begin()), 46 __end_(__fmt.end()), 47 __indexing_(__unknown), 48 __next_arg_id_(0), 49 __num_args_(__num_args) {} 50 51 basic_format_parse_context(const basic_format_parse_context&) = delete; 52 basic_format_parse_context& 53 operator=(const basic_format_parse_context&) = delete; 54 55 _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept { 56 return __begin_; 57 } 58 _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept { 59 return __end_; 60 } 61 _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(const_iterator __it) { 62 __begin_ = __it; 63 } 64 65 _LIBCPP_HIDE_FROM_ABI constexpr size_t next_arg_id() { 66 if (__indexing_ == __manual) 67 __throw_format_error("Using automatic argument numbering in manual " 68 "argument numbering mode"); 69 70 if (__indexing_ == __unknown) 71 __indexing_ = __automatic; 72 return __next_arg_id_++; 73 } 74 _LIBCPP_HIDE_FROM_ABI constexpr void check_arg_id(size_t __id) { 75 if (__indexing_ == __automatic) 76 __throw_format_error("Using manual argument numbering in automatic " 77 "argument numbering mode"); 78 79 if (__indexing_ == __unknown) 80 __indexing_ = __manual; 81 82 // Throws an exception to make the expression a non core constant 83 // expression as required by: 84 // [format.parse.ctx]/11 85 // Remarks: Call expressions where id >= num_args_ are not core constant 86 // expressions ([expr.const]). 87 // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the 88 // behavior when id >= num_args_. 89 if (is_constant_evaluated() && __id >= __num_args_) 90 __throw_format_error("Argument index outside the valid range"); 91 } 92 93 private: 94 iterator __begin_; 95 iterator __end_; 96 enum _Indexing { __unknown, __manual, __automatic }; 97 _Indexing __indexing_; 98 size_t __next_arg_id_; 99 size_t __num_args_; 100 }; 101 102 using format_parse_context = basic_format_parse_context<char>; 103 using wformat_parse_context = basic_format_parse_context<wchar_t>; 104 105 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED) 106 107 #endif //_LIBCPP_STD_VER > 17 108 109 _LIBCPP_END_NAMESPACE_STD 110 111 _LIBCPP_POP_MACROS 112 113 #endif // _LIBCPP___FORMAT_FORMAT_PARSE_CONTEXT_H 114