17 #include <type_traits>
25 #if FMT_HAS_INCLUDE(<version>)
29 #if FMT_CPLUSPLUS >= 201703L
30 # if FMT_HAS_INCLUDE(<filesystem>)
31 # include <filesystem>
33 # if FMT_HAS_INCLUDE(<variant>)
36 # if FMT_HAS_INCLUDE(<optional>)
41 #if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<source_location>)
42 # include <source_location>
46 #if FMT_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__)
50 # ifndef __GABIXX_CXXABI_H__
51 # define FMT_HAS_ABI_CXA_DEMANGLE
56 #ifndef FMT_USE_TYPEID
58 # if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || FMT_MSC_VERSION || \
59 defined(__INTEL_RTTI__) || defined(__RTTI)
60 # define FMT_USE_TYPEID 1
62 # define FMT_USE_TYPEID 0
67 #ifndef FMT_CPP_LIB_FILESYSTEM
68 # ifdef __cpp_lib_filesystem
69 # define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem
71 # define FMT_CPP_LIB_FILESYSTEM 0
75 #ifndef FMT_CPP_LIB_VARIANT
76 # ifdef __cpp_lib_variant
77 # define FMT_CPP_LIB_VARIANT __cpp_lib_variant
79 # define FMT_CPP_LIB_VARIANT 0
83 #if FMT_CPP_LIB_FILESYSTEM
88 template <
typename Char,
typename PathChar>
89 auto get_path_string(
const std::filesystem::path& p,
90 const std::basic_string<PathChar>& native) {
91 if constexpr (std::is_same_v<Char, char> && std::is_same_v<PathChar, wchar_t>)
94 return p.string<Char>();
97 template <
typename Char,
typename PathChar>
99 const std::filesystem::path& p,
100 const std::basic_string<PathChar>& native) {
101 if constexpr (std::is_same_v<Char, char> &&
102 std::is_same_v<PathChar, wchar_t>) {
104 write_escaped_string<wchar_t>(std::back_inserter(buf), native);
107 }
else if constexpr (std::is_same_v<Char, PathChar>) {
108 write_escaped_string<std::filesystem::path::value_type>(
109 std::back_inserter(quoted), native);
111 write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>());
118 template <
typename Char>
struct formatter<
std::filesystem::path, Char> {
128 template <
typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) {
129 auto it = ctx.begin(), end = ctx.end();
130 if (it == end)
return it;
133 if (it == end)
return it;
136 if (it != end && *it ==
'?') {
140 if (it != end && (*it ==
'g')) path_type_ = *it++;
144 template <
typename FormatContext>
145 auto format(
const std::filesystem::path& p, FormatContext& ctx)
const {
148 auto path_string = !path_type_ ? p.native() : p.generic_wstring();
150 auto path_string = !path_type_ ? p.native() : p.generic_string();
153 detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_,
156 auto s = detail::get_path_string<Char>(p, path_string);
160 detail::write_escaped_path(quoted, p, path_string);
167 #endif // FMT_CPP_LIB_FILESYSTEM
171 template <std::
size_t N,
typename Char>
176 const std::bitset<N>&
bs;
178 template <
typename OutputIt>
180 for (
auto pos = N; pos > 0; --pos) {
181 out = detail::write<Char>(out, bs[pos - 1] ? Char(
'1') : Char(
'0'));
189 template <
typename FormatContext>
190 auto format(
const std::bitset<N>& bs, FormatContext& ctx)
const
191 -> decltype(ctx.out()) {
197 template <
typename Char>
201 #ifdef __cpp_lib_optional
204 template <
typename T,
typename Char>
217 -> decltype(u.set_debug_format(
set)) {
218 u.set_debug_format(
set);
225 template <
typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) {
227 return underlying_.parse(ctx);
230 template <
typename FormatContext>
231 auto format(
const std::optional<T>& opt, FormatContext& ctx)
const
232 -> decltype(ctx.out()) {
233 if (!opt)
return detail::write<Char>(ctx.out(),
none);
235 auto out = ctx.out();
236 out = detail::write<Char>(out, optional);
238 out = underlying_.format(*opt, ctx);
243 #endif // __cpp_lib_optional
245 #ifdef __cpp_lib_source_location
249 template <
typename ParseContext>
FMT_CONSTEXPR auto parse(ParseContext& ctx) {
253 template <
typename FormatContext>
254 auto format(
const std::source_location& loc, FormatContext& ctx)
const
255 -> decltype(ctx.out()) {
256 auto out = ctx.out();
259 out = detail::write<char>(out, loc.line());
261 out = detail::write<char>(out, loc.column());
270 #if FMT_CPP_LIB_VARIANT
274 template <
typename T>
275 using variant_index_sequence =
276 std::make_index_sequence<std::variant_size<T>::value>;
279 template <
typename... Types>
283 template <
typename T,
typename C>
class is_variant_formattable_ {
285 static std::conjunction<
287 check(std::index_sequence<Is...>);
290 static constexpr
const bool value =
291 decltype(
check(variant_index_sequence<T>{}))::
value;
294 template <
typename Char,
typename OutputIt,
typename T>
295 auto write_variant_alternative(OutputIt out,
const T& v) -> OutputIt {
296 if constexpr (is_string<T>::value)
298 else if constexpr (std::is_same_v<T, Char>)
301 return write<Char>(out, v);
306 template <
typename T>
struct is_variant_like {
307 static constexpr
const bool value = detail::is_variant_like_<T>::value;
310 template <
typename T,
typename C>
struct is_variant_formattable {
311 static constexpr
const bool value =
312 detail::is_variant_formattable_<T, C>::value;
317 template <
typename ParseContext>
318 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
322 template <
typename FormatContext>
323 auto format(
const std::monostate&, FormatContext& ctx)
const
324 -> decltype(ctx.out()) {
325 return detail::write<Char>(ctx.out(),
"monostate");
330 template <
typename Variant,
typename Char>
334 is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
335 template <
typename ParseContext>
336 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
340 template <
typename FormatContext>
341 auto format(
const Variant& value, FormatContext& ctx)
const
342 -> decltype(ctx.out()) {
343 auto out = ctx.out();
345 out = detail::write<Char>(out,
"variant(");
349 out = detail::write_variant_alternative<Char>(out, v);
353 FMT_CATCH(
const std::bad_variant_access&) {
354 detail::write<Char>(out,
"valueless by exception");
361 #endif // FMT_CPP_LIB_VARIANT
366 template <
typename ParseContext>
371 template <
typename FormatContext>
373 -> decltype(ctx.out()) {
374 auto out = ctx.out();
376 out = detail::write<Char>(out, Char(
':'));
377 out = detail::write<Char>(out, ec.value());
383 template <
typename T,
typename Char>
386 typename
std::enable_if<std::is_base_of<std::exception, T>::value>
::type> {
388 bool with_typename_ =
false;
392 -> decltype(ctx.begin()) {
393 auto it = ctx.begin();
394 auto end = ctx.end();
395 if (it == end || *it ==
'}')
return it;
403 template <
typename OutputIt>
407 auto out = ctx.out();
412 const std::type_info& ti =
typeid(ex);
413 # ifdef FMT_HAS_ABI_CXA_DEMANGLE
416 std::unique_ptr<char,
void (*)(
void*)> demangled_name_ptr(
417 abi::__cxa_demangle(ti.name(),
nullptr, &
size, &status), &std::free);
420 if (demangled_name_ptr) {
421 demangled_name_view = demangled_name_ptr.get();
430 if (demangled_name_view.starts_with(
"std::")) {
431 char* begin = demangled_name_ptr.get();
432 char* to = begin + 5;
433 for (
char *from = to, *end = begin + demangled_name_view.size();
436 if (from[0] ==
'_' && from[1] ==
'_') {
437 char*
next = from + 1;
439 if (
next[0] ==
':' &&
next[1] ==
':') {
452 # elif FMT_MSC_VERSION
456 else if (demangled_name_view.
starts_with(
"struct "))
471 template <
typename T,
typename Enable =
void>
474 template <
typename T>
480 std::is_convertible<T, bool>::value &&
484 #ifdef _LIBCPP_VERSION
488 template <
typename C>
490 static constexpr
const bool value =
true;
501 template <
typename BitRef,
typename Char>
505 template <
typename FormatContext>
507 -> decltype(ctx.out()) {
513 template <
typename T,
typename Char>
517 template <
typename FormatContext>
518 auto format(
const std::atomic<T>& v, FormatContext& ctx)
const
519 -> decltype(ctx.out()) {
524 #ifdef __cpp_lib_atomic_flag_test
526 template <
typename Char>
528 template <
typename FormatContext>
529 auto format(
const std::atomic_flag& v, FormatContext& ctx)
const
530 -> decltype(ctx.out()) {
534 #endif // __cpp_lib_atomic_flag_test