Skip to content

Commit 75cdef1

Browse files
committed
Added std::type_info formatter
* Added std::type_info formatter; * Reused std::type_info formatter in std::exception formatters; * Updated MSVC std::type_info outputting to exclude all class, struct and enum occurences.
1 parent 1768bf9 commit 75cdef1

File tree

1 file changed

+69
-31
lines changed

1 file changed

+69
-31
lines changed

Diff for: include/fmt/std.h

+69-31
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# include <cstdlib>
1616
# include <exception>
1717
# include <memory>
18+
# include <string>
1819
# include <thread>
1920
# include <type_traits>
2021
# include <typeinfo>
@@ -416,36 +417,34 @@ template <typename Char> struct formatter<std::error_code, Char> {
416417
}
417418
};
418419

419-
FMT_EXPORT
420-
template <typename T, typename Char>
421-
struct formatter<
422-
T, Char, // DEPRECATED! Mixing code unit types.
423-
typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
424-
private:
425-
bool with_typename_ = false;
420+
#if FMT_USE_RTTI
421+
namespace details {
422+
template <typename Char>
423+
inline void remove_all_substrings(
424+
std::basic_string<Char>& src,
425+
type_identity_t<basic_string_view<Char>> pattern) {
426+
const auto pattern_length = pattern.size();
427+
for (auto i = src.find(pattern.data(), 0, pattern_length);
428+
i != std::basic_string<Char>::npos;
429+
i = src.find(pattern.data(), 0, pattern_length))
430+
src.erase(i, pattern_length);
431+
}
432+
} // namespace details
426433

434+
FMT_EXPORT
435+
template <typename Char>
436+
struct formatter<std::type_info, Char // DEPRECATED! Mixing code unit types.
437+
> {
427438
public:
428439
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
429440
-> decltype(ctx.begin()) {
430-
auto it = ctx.begin();
431-
auto end = ctx.end();
432-
if (it == end || *it == '}') return it;
433-
if (*it == 't') {
434-
++it;
435-
with_typename_ = FMT_USE_RTTI != 0;
436-
}
437-
return it;
441+
return ctx.begin();
438442
}
439443

440444
template <typename Context>
441-
auto format(const std::exception& ex, Context& ctx) const
445+
auto format(const std::type_info& ti, Context& ctx) const
442446
-> decltype(ctx.out()) {
443447
auto out = ctx.out();
444-
if (!with_typename_)
445-
return detail::write_bytes<Char>(out, string_view(ex.what()));
446-
447-
#if FMT_USE_RTTI
448-
const std::type_info& ti = typeid(ex);
449448
# ifdef FMT_HAS_ABI_CXA_DEMANGLE
450449
int status = 0;
451450
std::size_t size = 0;
@@ -484,22 +483,61 @@ struct formatter<
484483
} else {
485484
demangled_name_view = string_view(ti.name());
486485
}
487-
out = detail::write_bytes<Char>(out, demangled_name_view);
486+
return detail::write_bytes<Char>(out, demangled_name_view);
488487
# elif FMT_MSC_VERSION
489-
string_view demangled_name_view(ti.name());
490-
if (demangled_name_view.starts_with("class "))
491-
demangled_name_view.remove_prefix(6);
492-
else if (demangled_name_view.starts_with("struct "))
493-
demangled_name_view.remove_prefix(7);
494-
out = detail::write_bytes<Char>(out, demangled_name_view);
488+
std::basic_string<Char> demangled_name(ti.name());
489+
auto class_space =
490+
detail::string_literal<Char, 'c', 'l', 'a', 's', 's', ' '>{};
491+
auto enum_space = detail::string_literal<Char, 'e', 'n', 'u', 'm', ' '>{};
492+
auto struct_space =
493+
detail::string_literal<Char, 's', 't', 'r', 'u', 'c', 't', ' '>{};
494+
details::remove_all_substrings(demangled_name, class_space);
495+
details::remove_all_substrings(demangled_name, enum_space);
496+
details::remove_all_substrings(demangled_name, struct_space);
497+
return detail::write_bytes<Char>(out, demangled_name);
495498
# else
496-
out = detail::write_bytes<Char>(out, string_view(ti.name())
497-
});
499+
return detail::write_bytes<Char>(out, string_view(ti.name()));
498500
# endif
501+
}
502+
};
503+
#endif
504+
505+
FMT_EXPORT
506+
template <typename T, typename Char>
507+
struct formatter<
508+
T, Char, // DEPRECATED! Mixing code unit types.
509+
typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
510+
private:
511+
bool with_typename_ = false;
512+
513+
public:
514+
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
515+
-> decltype(ctx.begin()) {
516+
auto it = ctx.begin();
517+
auto end = ctx.end();
518+
if (it == end || *it == '}') return it;
519+
if (*it == 't') {
520+
++it;
521+
with_typename_ = FMT_USE_RTTI != 0;
522+
}
523+
return it;
524+
}
525+
526+
template <typename Context>
527+
auto format(const std::exception& ex, Context& ctx) const
528+
-> decltype(ctx.out()) {
529+
auto out = ctx.out();
530+
if (!with_typename_)
531+
return detail::write_bytes<Char>(out, string_view(ex.what()));
532+
533+
#if FMT_USE_RTTI
534+
const std::type_info& ti = typeid(ex);
535+
auto format_imag = detail::string_literal<Char, '{', '}'>{};
536+
out = fmt::format_to(out, basic_string_view<Char>(format_imag), ti);
537+
#endif
499538
*out++ = ':';
500539
*out++ = ' ';
501540
return detail::write_bytes<Char>(out, string_view(ex.what()));
502-
#endif
503541
}
504542
};
505543

0 commit comments

Comments
 (0)