Home | History | Annotate | Line # | Download | only in include
      1 // -*- 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 
     15 namespace 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   };
     22 
     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>;
     54 }
     55 
     56 */
     57 
     58 #include <__config>
     59 #include <stdexcept>
     60 #include <string_view>
     61 #include <version>
     62 
     63 #ifdef _LIBCPP_NO_EXCEPTIONS
     64 #include <cstdlib>
     65 #endif
     66 
     67 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
     68 #  pragma GCC system_header
     69 #endif
     70 
     71 _LIBCPP_PUSH_MACROS
     72 #include <__undef_macros>
     73 
     74 _LIBCPP_BEGIN_NAMESPACE_STD
     75 
     76 #if _LIBCPP_STD_VER > 17
     77 
     78 class _LIBCPP_EXCEPTION_ABI format_error : public runtime_error {
     79 public:
     80   _LIBCPP_INLINE_VISIBILITY explicit format_error(const string& __s)
     81       : runtime_error(__s) {}
     82   _LIBCPP_INLINE_VISIBILITY explicit format_error(const char* __s)
     83       : runtime_error(__s) {}
     84   virtual ~format_error() noexcept;
     85 };
     86 
     87 // TODO FMT Remove this once we require compilers with proper C++20 support.
     88 // If the compiler has no concepts support, the format header will be disabled.
     89 // Without concepts support enable_if needs to be used and that too much effort
     90 // to support compilers with partial C++20 support.
     91 #if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
     92 
     93 _LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void
     94 __throw_format_error(const char* __s) {
     95 #ifndef _LIBCPP_NO_EXCEPTIONS
     96   throw format_error(__s);
     97 #else
     98   (void)__s;
     99   _VSTD::abort();
    100 #endif
    101 }
    102 
    103 template <class _CharT>
    104 class _LIBCPP_TEMPLATE_VIS basic_format_parse_context {
    105 public:
    106   using char_type = _CharT;
    107   using const_iterator =
    108       typename basic_string_view<_CharT>::const_iterator;
    109   using iterator = const_iterator;
    110 
    111 public:
    112   _LIBCPP_INLINE_VISIBILITY
    113   constexpr explicit basic_format_parse_context(
    114       basic_string_view<_CharT> __fmt, size_t __num_args = 0) noexcept
    115       : __begin_(__fmt.begin()),
    116         __end_(__fmt.end()),
    117         __indexing_(__unknown),
    118         __next_arg_id_(0),
    119         __num_args_(__num_args) {}
    120 
    121   basic_format_parse_context(const basic_format_parse_context&) = delete;
    122   basic_format_parse_context&
    123   operator=(const basic_format_parse_context&) = delete;
    124 
    125   _LIBCPP_INLINE_VISIBILITY constexpr const_iterator begin() const noexcept {
    126     return __begin_;
    127   }
    128   _LIBCPP_INLINE_VISIBILITY constexpr const_iterator end() const noexcept {
    129     return __end_;
    130   }
    131   _LIBCPP_INLINE_VISIBILITY constexpr void advance_to(const_iterator __it) {
    132     __begin_ = __it;
    133   }
    134 
    135   _LIBCPP_INLINE_VISIBILITY constexpr size_t next_arg_id() {
    136     if (__indexing_ == __manual)
    137       __throw_format_error("Using automatic argument numbering in manual "
    138                            "argument numbering mode");
    139 
    140     if (__indexing_ == __unknown)
    141       __indexing_ = __automatic;
    142     return __next_arg_id_++;
    143   }
    144   _LIBCPP_INLINE_VISIBILITY constexpr void check_arg_id(size_t __id) {
    145     if (__indexing_ == __automatic)
    146       __throw_format_error("Using manual argument numbering in automatic "
    147                            "argument numbering mode");
    148 
    149     if (__indexing_ == __unknown)
    150       __indexing_ = __manual;
    151 
    152     // Throws an exception to make the expression a non core constant
    153     // expression as required by:
    154     // [format.parse.ctx]/11
    155     //   Remarks: Call expressions where id >= num_args_ are not core constant
    156     //   expressions ([expr.const]).
    157     // Note: the Throws clause [format.parse.ctx]/10 doesn't specify the
    158     // behavior when id >= num_args_.
    159     if (is_constant_evaluated() && __id >= __num_args_)
    160       __throw_format_error("Argument index outside the valid range");
    161   }
    162 
    163 private:
    164   iterator __begin_;
    165   iterator __end_;
    166   enum _Indexing { __unknown, __manual, __automatic };
    167   _Indexing __indexing_;
    168   size_t __next_arg_id_;
    169   size_t __num_args_;
    170 };
    171 
    172 using format_parse_context = basic_format_parse_context<char>;
    173 using wformat_parse_context = basic_format_parse_context<wchar_t>;
    174 
    175 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)
    176 #endif //_LIBCPP_STD_VER > 17
    177 
    178 _LIBCPP_END_NAMESPACE_STD
    179 
    180 _LIBCPP_POP_MACROS
    181 
    182 #endif // _LIBCPP_FORMAT
    183