blob: d755062c53fd4ab0040ad98cb821a4d919b37d06 [file] [log] [blame]
Mark de Weverdf5fd832020-11-26 19:12:18 +01001// -*- C++ -*-
2//===--------------------------- format -----------------------------------===//
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
11#define _LIBCPP_FORMAT
12
13/*
14
15namespace std {
16 // [format.error], class format_error
17 class format_error : public runtime_error {
18 public:
19 explicit format_error(const string& what_arg);
20 explicit format_error(const char* what_arg);
21 };
Mark de Wever6a67a5f2021-02-02 18:10:33 +010022
23 // [format.parse.ctx], class template basic_format_parse_context
24 template<class charT>
25 class basic_format_parse_context {
26 public:
27 using char_type = charT;
28 using const_iterator = typename basic_string_view<charT>::const_iterator;
29 using iterator = const_iterator;
30
31 private:
32 iterator begin_; // exposition only
33 iterator end_; // exposition only
34 enum indexing { unknown, manual, automatic }; // exposition only
35 indexing indexing_; // exposition only
36 size_t next_arg_id_; // exposition only
37 size_t num_args_; // exposition only
38
39 public:
40 constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
41 size_t num_args = 0) noexcept;
42 basic_format_parse_context(const basic_format_parse_context&) = delete;
43 basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
44
45 constexpr const_iterator begin() const noexcept;
46 constexpr const_iterator end() const noexcept;
47 constexpr void advance_to(const_iterator it);
48
49 constexpr size_t next_arg_id();
50 constexpr void check_arg_id(size_t id);
51 };
52 using format_parse_context = basic_format_parse_context<char>;
53 using wformat_parse_context = basic_format_parse_context<wchar_t>;
Mark de Weverdf5fd832020-11-26 19:12:18 +010054}
55
56*/
57
58#include <__config>
Mark de Wever1aef5d02021-04-25 17:58:03 +020059#include <__format/format_error.h>
Mark de Wever6a67a5f2021-02-02 18:10:33 +010060#include <string_view>
Mark de Weverdf5fd832020-11-26 19:12:18 +010061#include <version>
62
63#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
64# pragma GCC system_header
65#endif
66
67_LIBCPP_PUSH_MACROS
68#include <__undef_macros>
69
70_LIBCPP_BEGIN_NAMESPACE_STD
71
72#if _LIBCPP_STD_VER > 17
73
Mark de Wever62459b52021-02-11 19:11:20 +010074// TODO FMT Remove this once we require compilers with proper C++20 support.
75// If the compiler has no concepts support, the format header will be disabled.
76// Without concepts support enable_if needs to be used and that too much effort
77// to support compilers with partial C++20 support.
78#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
79
Mark de Wever6a67a5f2021-02-02 18:10:33 +010080template <class _CharT>
81class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
82public:
83 using char_type = _CharT;
84 using const_iterator =
Mark de Wever9d7aa7a2021-05-09 18:22:52 +020085 typename basic_string_view<_CharT>::const_iterator;
Mark de Wever6a67a5f2021-02-02 18:10:33 +010086 using iterator = const_iterator;
87
88public:
89 _LIBCPP_INLINE_VISIBILITY
90 constexpr explicit basic_format_parse_context(
Mark de Wever9d7aa7a2021-05-09 18:22:52 +020091 basic_string_view<_CharT> __fmt, size_t __num_args = 0) noexcept
Mark de Wever6a67a5f2021-02-02 18:10:33 +010092 : __begin_(__fmt.begin()),
93 __end_(__fmt.end()),
94 __indexing_(__unknown),
95 __next_arg_id_(0),
96 __num_args_(__num_args) {}
97
98 basic_format_parse_context(const basic_format_parse_context&) = delete;
99 basic_format_parse_context&
100 operator=(const basic_format_parse_context&) = delete;
101
102 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator begin() const noexcept {
103 return __begin_;
104 }
105 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator end() const noexcept {
106 return __end_;
107 }
108 _LIBCPP_INLINE_VISIBILITY constexpr void advance_to(const_iterator __it) {
109 __begin_ = __it;
110 }
111
112 _LIBCPP_INLINE_VISIBILITY constexpr size_t next_arg_id() {
113 if (__indexing_ == __manual)
114 __throw_format_error("Using automatic argument numbering in manual "
115 "argument numbering mode");
116
117 if (__indexing_ == __unknown)
118 __indexing_ = __automatic;
119 return __next_arg_id_++;
120 }
121 _LIBCPP_INLINE_VISIBILITY constexpr void check_arg_id(size_t __id) {
122 if (__indexing_ == __automatic)
123 __throw_format_error("Using manual argument numbering in automatic "
124 "argument numbering mode");
125
126 if (__indexing_ == __unknown)
127 __indexing_ = __manual;
128
129 // Throws an exception to make the expression a non core constant
130 // expression as required by:
131 // [format.parse.ctx]/11
132 // Remarks: Call expressions where id >= num_args_ are not core constant
133 // expressions ([expr.const]).
134 // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the
135 // behavior when id >= num_args_.
Mark de Wever9d7aa7a2021-05-09 18:22:52 +0200136 if (is_constant_evaluated() && __id >= __num_args_)
Mark de Wever6a67a5f2021-02-02 18:10:33 +0100137 __throw_format_error("Argument index outside the valid range");
138 }
139
140private:
141 iterator __begin_;
142 iterator __end_;
143 enum _Indexing { __unknown, __manual, __automatic };
144 _Indexing __indexing_;
145 size_t __next_arg_id_;
146 size_t __num_args_;
147};
148
149using format_parse_context = basic_format_parse_context<char>;
150using wformat_parse_context = basic_format_parse_context<wchar_t>;
151
Mark de Wever72fe7372021-02-11 18:52:47 +0100152#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
Mark de Weverdf5fd832020-11-26 19:12:18 +0100153#endif //_LIBCPP_STD_VER > 17
154
155_LIBCPP_END_NAMESPACE_STD
156
157_LIBCPP_POP_MACROS
158
159#endif // _LIBCPP_FORMAT