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