summaryrefslogtreecommitdiffstats
path: root/src/fmtlib/fmt/std.h
blob: 227f4841123d3befe9b64029e80d233dc3d64601 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Formatting library for C++ - formatters for standard library types
//
// Copyright (c) 2012 - present, Victor Zverovich
// All rights reserved.
//
// For the license information refer to format.h.

#ifndef FMT_STD_H_
#define FMT_STD_H_

#include <thread>
#include <type_traits>
#include <utility>

#include "ostream.h"

#if FMT_HAS_INCLUDE(<version>)
#  include <version>
#endif
// Checking FMT_CPLUSPLUS for warning suppression in MSVC.
#if FMT_CPLUSPLUS >= 201703L
#  if FMT_HAS_INCLUDE(<filesystem>)
#    include <filesystem>
#  endif
#  if FMT_HAS_INCLUDE(<variant>)
#    include <variant>
#  endif
#endif

#ifdef __cpp_lib_filesystem
FMT_BEGIN_NAMESPACE

namespace detail {

template <typename Char>
void write_escaped_path(basic_memory_buffer<Char>& quoted,
                        const std::filesystem::path& p) {
  write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>());
}
#  ifdef _WIN32
template <>
inline void write_escaped_path<char>(basic_memory_buffer<char>& quoted,
                                     const std::filesystem::path& p) {
  auto s = p.u8string();
  write_escaped_string<char>(
      std::back_inserter(quoted),
      string_view(reinterpret_cast<const char*>(s.c_str()), s.size()));
}
#  endif
template <>
inline void write_escaped_path<std::filesystem::path::value_type>(
    basic_memory_buffer<std::filesystem::path::value_type>& quoted,
    const std::filesystem::path& p) {
  write_escaped_string<std::filesystem::path::value_type>(
      std::back_inserter(quoted), p.native());
}

}  // namespace detail

#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920
// For MSVC 2017 and earlier using the partial specialization
// would cause an ambiguity error, therefore we provide it only
// conditionally.
template <typename Char>
struct formatter<std::filesystem::path, Char>
    : formatter<basic_string_view<Char>> {
  template <typename FormatContext>
  auto format(const std::filesystem::path& p, FormatContext& ctx) const ->
      typename FormatContext::iterator {
    basic_memory_buffer<Char> quoted;
    detail::write_escaped_path(quoted, p);
    return formatter<basic_string_view<Char>>::format(
        basic_string_view<Char>(quoted.data(), quoted.size()), ctx);
  }
};
#endif
FMT_END_NAMESPACE
#endif

FMT_BEGIN_NAMESPACE
template <typename Char>
struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
FMT_END_NAMESPACE

#ifdef __cpp_lib_variant
FMT_BEGIN_NAMESPACE
template <typename Char> struct formatter<std::monostate, Char> {
  template <typename ParseContext>
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(const std::monostate&, FormatContext& ctx) const
      -> decltype(ctx.out()) {
    auto out = ctx.out();
    out = detail::write<Char>(out, "monostate");
    return out;
  }
};

namespace detail {

template <typename T>
using variant_index_sequence =
    std::make_index_sequence<std::variant_size<T>::value>;

// variant_size and variant_alternative check.
template <typename T, typename U = void>
struct is_variant_like_ : std::false_type {};
template <typename T>
struct is_variant_like_<T, std::void_t<decltype(std::variant_size<T>::value)>>
    : std::true_type {};

// formattable element check
template <typename T, typename C> class is_variant_formattable_ {
  template <std::size_t... I>
  static std::conjunction<
      is_formattable<std::variant_alternative_t<I, T>, C>...>
      check(std::index_sequence<I...>);

 public:
  static constexpr const bool value =
      decltype(check(variant_index_sequence<T>{}))::value;
};

template <typename Char, typename OutputIt, typename T>
auto write_variant_alternative(OutputIt out, const T& v) -> OutputIt {
  if constexpr (is_string<T>::value)
    return write_escaped_string<Char>(out, detail::to_string_view(v));
  else if constexpr (std::is_same_v<T, Char>)
    return write_escaped_char(out, v);
  else
    return write<Char>(out, v);
}

}  // namespace detail

template <typename T> struct is_variant_like {
  static constexpr const bool value = detail::is_variant_like_<T>::value;
};

template <typename T, typename C> struct is_variant_formattable {
  static constexpr const bool value =
      detail::is_variant_formattable_<T, C>::value;
};

template <typename Variant, typename Char>
struct formatter<
    Variant, Char,
    std::enable_if_t<std::conjunction_v<
        is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
  template <typename ParseContext>
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
    return ctx.begin();
  }

  template <typename FormatContext>
  auto format(const Variant& value, FormatContext& ctx) const
      -> decltype(ctx.out()) {
    auto out = ctx.out();

    out = detail::write<Char>(out, "variant(");
    std::visit(
        [&](const auto& v) {
          out = detail::write_variant_alternative<Char>(out, v);
        },
        value);
    *out++ = ')';
    return out;
  }
};
FMT_END_NAMESPACE
#endif

#endif  // FMT_STD_H_