1*c303c47eSjoerg// -*- C++ -*-
2*c303c47eSjoerg//===--------------------------- format -----------------------------------===//
3*c303c47eSjoerg//
4*c303c47eSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*c303c47eSjoerg// See https://llvm.org/LICENSE.txt for license information.
6*c303c47eSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*c303c47eSjoerg//
8*c303c47eSjoerg//===----------------------------------------------------------------------===//
9*c303c47eSjoerg
10*c303c47eSjoerg#ifndef _LIBCPP_FORMAT
11*c303c47eSjoerg#define _LIBCPP_FORMAT
12*c303c47eSjoerg
13*c303c47eSjoerg/*
14*c303c47eSjoerg
15*c303c47eSjoergnamespace std {
16*c303c47eSjoerg  // [format.error], class format_error
17*c303c47eSjoerg  class format_error : public runtime_error {
18*c303c47eSjoerg  public:
19*c303c47eSjoerg    explicit format_error(const string& what_arg);
20*c303c47eSjoerg    explicit format_error(const char* what_arg);
21*c303c47eSjoerg  };
22*c303c47eSjoerg
23*c303c47eSjoerg  // [format.parse.ctx], class template basic_format_parse_context
24*c303c47eSjoerg  template<class charT>
25*c303c47eSjoerg  class basic_format_parse_context {
26*c303c47eSjoerg  public:
27*c303c47eSjoerg    using char_type = charT;
28*c303c47eSjoerg    using const_iterator = typename basic_string_view<charT>::const_iterator;
29*c303c47eSjoerg    using iterator = const_iterator;
30*c303c47eSjoerg
31*c303c47eSjoerg  private:
32*c303c47eSjoerg    iterator begin_;                                    // exposition only
33*c303c47eSjoerg    iterator end_;                                      // exposition only
34*c303c47eSjoerg    enum indexing { unknown, manual, automatic };       // exposition only
35*c303c47eSjoerg    indexing indexing_;                                 // exposition only
36*c303c47eSjoerg    size_t next_arg_id_;                                // exposition only
37*c303c47eSjoerg    size_t num_args_;                                   // exposition only
38*c303c47eSjoerg
39*c303c47eSjoerg  public:
40*c303c47eSjoerg    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
41*c303c47eSjoerg                                                  size_t num_args = 0) noexcept;
42*c303c47eSjoerg    basic_format_parse_context(const basic_format_parse_context&) = delete;
43*c303c47eSjoerg    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
44*c303c47eSjoerg
45*c303c47eSjoerg    constexpr const_iterator begin() const noexcept;
46*c303c47eSjoerg    constexpr const_iterator end() const noexcept;
47*c303c47eSjoerg    constexpr void advance_to(const_iterator it);
48*c303c47eSjoerg
49*c303c47eSjoerg    constexpr size_t next_arg_id();
50*c303c47eSjoerg    constexpr void check_arg_id(size_t id);
51*c303c47eSjoerg  };
52*c303c47eSjoerg  using format_parse_context = basic_format_parse_context<char>;
53*c303c47eSjoerg  using wformat_parse_context = basic_format_parse_context<wchar_t>;
54*c303c47eSjoerg}
55*c303c47eSjoerg
56*c303c47eSjoerg*/
57*c303c47eSjoerg
58*c303c47eSjoerg#include <__config>
59*c303c47eSjoerg#include <stdexcept>
60*c303c47eSjoerg#include <string_view>
61*c303c47eSjoerg#include <version>
62*c303c47eSjoerg
63*c303c47eSjoerg#ifdef _LIBCPP_NO_EXCEPTIONS
64*c303c47eSjoerg#include <cstdlib>
65*c303c47eSjoerg#endif
66*c303c47eSjoerg
67*c303c47eSjoerg#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
68*c303c47eSjoerg#  pragma GCC system_header
69*c303c47eSjoerg#endif
70*c303c47eSjoerg
71*c303c47eSjoerg_LIBCPP_PUSH_MACROS
72*c303c47eSjoerg#include <__undef_macros>
73*c303c47eSjoerg
74*c303c47eSjoerg_LIBCPP_BEGIN_NAMESPACE_STD
75*c303c47eSjoerg
76*c303c47eSjoerg#if _LIBCPP_STD_VER > 17
77*c303c47eSjoerg
78*c303c47eSjoergclass _LIBCPP_EXCEPTION_ABI format_error : public runtime_error {
79*c303c47eSjoergpublic:
80*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY explicit format_error(const string& __s)
81*c303c47eSjoerg      : runtime_error(__s) {}
82*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY explicit format_error(const char* __s)
83*c303c47eSjoerg      : runtime_error(__s) {}
84*c303c47eSjoerg  virtual ~format_error() noexcept;
85*c303c47eSjoerg};
86*c303c47eSjoerg
87*c303c47eSjoerg// TODO FMT Remove this once we require compilers with proper C++20 support.
88*c303c47eSjoerg// If the compiler has no concepts support, the format header will be disabled.
89*c303c47eSjoerg// Without concepts support enable_if needs to be used and that too much effort
90*c303c47eSjoerg// to support compilers with partial C++20 support.
91*c303c47eSjoerg#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
92*c303c47eSjoerg
93*c303c47eSjoerg_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void
94*c303c47eSjoerg__throw_format_error(const char* __s) {
95*c303c47eSjoerg#ifndef _LIBCPP_NO_EXCEPTIONS
96*c303c47eSjoerg  throw format_error(__s);
97*c303c47eSjoerg#else
98*c303c47eSjoerg  (void)__s;
99*c303c47eSjoerg  _VSTD::abort();
100*c303c47eSjoerg#endif
101*c303c47eSjoerg}
102*c303c47eSjoerg
103*c303c47eSjoergtemplate <class _CharT>
104*c303c47eSjoergclass _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
105*c303c47eSjoergpublic:
106*c303c47eSjoerg  using char_type = _CharT;
107*c303c47eSjoerg  using const_iterator =
108*c303c47eSjoerg      typename basic_string_view<_CharT>::const_iterator;
109*c303c47eSjoerg  using iterator = const_iterator;
110*c303c47eSjoerg
111*c303c47eSjoergpublic:
112*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY
113*c303c47eSjoerg  constexpr explicit basic_format_parse_context(
114*c303c47eSjoerg      basic_string_view<_CharT> __fmt, size_t __num_args = 0) noexcept
115*c303c47eSjoerg      : __begin_(__fmt.begin()),
116*c303c47eSjoerg        __end_(__fmt.end()),
117*c303c47eSjoerg        __indexing_(__unknown),
118*c303c47eSjoerg        __next_arg_id_(0),
119*c303c47eSjoerg        __num_args_(__num_args) {}
120*c303c47eSjoerg
121*c303c47eSjoerg  basic_format_parse_context(const basic_format_parse_context&) = delete;
122*c303c47eSjoerg  basic_format_parse_context&
123*c303c47eSjoerg  operator=(const basic_format_parse_context&) = delete;
124*c303c47eSjoerg
125*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY constexpr const_iterator begin() const noexcept {
126*c303c47eSjoerg    return __begin_;
127*c303c47eSjoerg  }
128*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY constexpr const_iterator end() const noexcept {
129*c303c47eSjoerg    return __end_;
130*c303c47eSjoerg  }
131*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY constexpr void advance_to(const_iterator __it) {
132*c303c47eSjoerg    __begin_ = __it;
133*c303c47eSjoerg  }
134*c303c47eSjoerg
135*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY constexpr size_t next_arg_id() {
136*c303c47eSjoerg    if (__indexing_ == __manual)
137*c303c47eSjoerg      __throw_format_error("Using automatic argument numbering in manual "
138*c303c47eSjoerg                           "argument numbering mode");
139*c303c47eSjoerg
140*c303c47eSjoerg    if (__indexing_ == __unknown)
141*c303c47eSjoerg      __indexing_ = __automatic;
142*c303c47eSjoerg    return __next_arg_id_++;
143*c303c47eSjoerg  }
144*c303c47eSjoerg  _LIBCPP_INLINE_VISIBILITY constexpr void check_arg_id(size_t __id) {
145*c303c47eSjoerg    if (__indexing_ == __automatic)
146*c303c47eSjoerg      __throw_format_error("Using manual argument numbering in automatic "
147*c303c47eSjoerg                           "argument numbering mode");
148*c303c47eSjoerg
149*c303c47eSjoerg    if (__indexing_ == __unknown)
150*c303c47eSjoerg      __indexing_ = __manual;
151*c303c47eSjoerg
152*c303c47eSjoerg    // Throws an exception to make the expression a non core constant
153*c303c47eSjoerg    // expression as required by:
154*c303c47eSjoerg    // [format.parse.ctx]/11
155*c303c47eSjoerg    //   Remarks: Call expressions where id >= num_args_ are not core constant
156*c303c47eSjoerg    //   expressions ([expr.const]).
157*c303c47eSjoerg    // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the
158*c303c47eSjoerg    // behavior when id >= num_args_.
159*c303c47eSjoerg    if (is_constant_evaluated() && __id >= __num_args_)
160*c303c47eSjoerg      __throw_format_error("Argument index outside the valid range");
161*c303c47eSjoerg  }
162*c303c47eSjoerg
163*c303c47eSjoergprivate:
164*c303c47eSjoerg  iterator __begin_;
165*c303c47eSjoerg  iterator __end_;
166*c303c47eSjoerg  enum _Indexing { __unknown, __manual, __automatic };
167*c303c47eSjoerg  _Indexing __indexing_;
168*c303c47eSjoerg  size_t __next_arg_id_;
169*c303c47eSjoerg  size_t __num_args_;
170*c303c47eSjoerg};
171*c303c47eSjoerg
172*c303c47eSjoergusing format_parse_context = basic_format_parse_context<char>;
173*c303c47eSjoergusing wformat_parse_context = basic_format_parse_context<wchar_t>;
174*c303c47eSjoerg
175*c303c47eSjoerg#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
176*c303c47eSjoerg#endif //_LIBCPP_STD_VER > 17
177*c303c47eSjoerg
178*c303c47eSjoerg_LIBCPP_END_NAMESPACE_STD
179*c303c47eSjoerg
180*c303c47eSjoerg_LIBCPP_POP_MACROS
181*c303c47eSjoerg
182*c303c47eSjoerg#endif // _LIBCPP_FORMAT
183